【问题标题】:Rails undefined local variable or method `line_item'Rails 未定义的局部变量或方法“line_item”
【发布时间】:2016-03-30 19:06:26
【问题描述】:

您好,我在为我在网站中构建的购物车创建此条件时遇到了一些麻烦,以便在零件销售时显示总数。在我的模式中,我有零件,line_items,它的 id 是零件和购物车,以及购物车。零件具有折扣属性。如果部件有折扣,它将显示折扣和部件的新价格。我的 line_items 有一个名为 line_item_discount 的方法,如果一个部分包含折扣,它将创建一个新的部分总和。尽管它显示了零件、折扣和新价格,但购物车总数并未更新。

我在这里创建了一个名为 total_price_with_discount 的方法

class Cart < ActiveRecord::Base
  has_many :order_items
  belongs_to :user
  has_many :line_items, dependent: :destroy

  def add_part(part_id)
    current_part = line_items.find_by(part_id: part_id)
    if current_part
      current_part.quantity += 1
    else
      current_part = line_items.build(part_id: part_id)
    end
    current_part
  end

  def total_price
    line_items.to_a.sum { |item| item.total_price}
  end

  def total_price_with_discount
    line_items.to_a.sum { |item| item.total_price.line_item_discount}
  end

现在我卡在 _cart 部分里面了我已经尝试了很多方法来创建条件,但我不断收到这样的消息

由于某种原因,购物车没有出现 line_items 或部件的实例。

这是我的购物车、零件和 line_items 表

create_table "carts", force: :cascade do |t|
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.integer  "user_id"
    t.integer  "quantity"
    t.decimal  "subtotal"
  end

create_table "parts", force: :cascade do |t|
    t.string  "name"
    t.text    "description"
    t.integer "category_id"
    t.integer "price"
    t.boolean "active"
    t.integer "discount"
    t.string  "image"
    t.integer "quantity"
  end
  create_table "line_items", force: :cascade do |t|
    t.integer  "part_id"
    t.integer  "cart_id"
    t.datetime "created_at",             null: false
    t.datetime "updated_at",             null: false
    t.integer  "quantity",   default: 1
  end

我的零件模型

class Part < ActiveRecord::Base
  has_many :order_items
  has_many :line_items

  before_destroy :ensure_not_referenced_by_any_line_item


  def ensure_not_referenced_by_any_line_item
    if line_items.empty?
      return true
    else
      errors.add(:base, 'Line Items present')
      return false
    end
end


  def subtotal
    parts.collect { |part| part.valid? ? (part.quantity * part.unit_price) : 0}.sum
  end


  def apply_discount
    price - (discount.to_f/100 * price)
  end

end

我的 line_items 模型

class LineItem < ActiveRecord::Base
  belongs_to :part
  belongs_to :cart

  def total_price
    part.price * quantity
  end

  def line_item_discount
    part.price - (part.discount.to_f/100 * part.price) * quantity
  end

end

这是引发错误的部分视图

<h2>Your Cart</h2> <table>
    <%= render(cart.line_items) %>
<tr class="total_line">
<td colspan="2">Total</td>
<%unless cart.line_items.part.discount?%>
<td class="total_cell"><%= number_to_currency(cart.total_price) %></td>
<%end%>

<%if cart.line_items.part.discount?%>
<td class="total_cell"><%= number_to_currency(cart.total_price_with_discount) %></td>
<%end%>
    </tr>
  </table>

<%= button_to 'Empty cart', cart, method: :delete, data: { confirm: 'Are you sure?' } %>

感谢您对此的任何帮助和建议

【问题讨论】:

    标签: ruby-on-rails activerecord undefined


    【解决方案1】:

    我要添加到Cart 模型:

    has_many :parts, through: :line_items
    

    Part 模型添加范围:

    scope :with_discounts, -> { where.not(discount: nil) }
    

    然后将视图更改为:

    <td class="total_cell">
      <%if cart.parts.with_discount.any?%>
        <%= number_to_currency(cart.total_price_with_discount) %>
      <%else%>
        <%= number_to_currency(cart.total_price) %>
      <%end%>
    </td>
    

    更新:与上面相比,我相信下面的代码更有效,但我会同时展示这两个选项并让你选择。

    下面我们将始终在LineItem 模型中的total_price 方法中使用line_item_discount

    def total_price
      (part.price * quantity) - line_item_discount
    end
    
    def line_item_discount
      return 0 if part.discount.blank?
      (part.discount.to_f/100 * part.price) * quantity
    end
    

    那么你甚至不需要视图中的 if 语句,total_price 可以工作:

    <td class="total_cell"><%= number_to_currency(cart.total_price) %></td>
    

    然后您可以从Cart 模型中删除total_price_with_discount 方法。

    我们还可以在Cart 模型中调整total_price 方法: (适用于任一代码选择)

    def total_price
      line_items.sum(:total_price)
    end
    

    【讨论】:

    • 我使用的是你提供给我的底部策略,看起来这段代码实际上是以实际百分比数字作为价格而不是折扣价
    • 哦,等一下,很抱歉我忘了从模型中取出 total_price_with_discount
    • 您还必须更改 line_item_discount 中的计算(我已经修改了答案中的代码)。它实际上是计算折扣后的总价,而不是折扣本身,刚刚实现。
    【解决方案2】:

    在您看来,您正在调用 cart.line_items.part,但 line_items 是多个 LineItem 对象的集合,.part 不是该集合对象的有效方法。

    正如您在错误中看到的那样,ActiveRecord::Associations::CollectionProxy 缺少 part 方法。

    您应该在LineItem 上创建一个范围,例如:

    scope :with_discounted_part, { joins(:part).where.not(part: { discount: nil }) }
    

    然后在你看来你可以这样做:

    <% if cart.line_items.with_discounted_part %>
    

    【讨论】:

      猜你喜欢
      • 2015-04-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-02
      • 2014-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多