Rails has_many: nil:NilClass 的未定义方法“*”

Rails has_many: undefined method `*' for nil:NilClass

我定义了一个关系,其中一个订单有很多订单项:

class Order < ActiveRecord::Base
  has_many :order_items
end

class OrderItem < ActiveRecord::Base
    belongs_to :book
    belongs_to :order
end

订单和订单商品已正确存储并存储了它们之间的关系。

我正在尝试显示所有订单的记录。为此,我需要访问订单商品的一些属性,例如数量或价格。

我定义了如下计算订单总价的方法,在Order模型中定义:

def total
    order_items.inject(0) { |sum, n| n.price * n.amount + sum }
end

我跟踪了错误,发现我在这个方法中遇到了错误,这是错误:ActionView::Template::Error (undefined method*' for nil:NilClass):`

是从视图中调用,以显示订单的总价。

实际上,如果我在此方法中添加一些行以尝试访问任何订单项属性,比如 order_items[0].price 我会立即收到错误消息。

我不明白为什么会这样。

我定义的关系与 ShoppingCartShoppingCartItems 完全相同,但没有遇到这个问题。

此外,我正在开发的订单和订单项目 类 与我之前使用 Rails 3.2.9 所做的项目非常相似,并且运行良好。

我能做什么?

您的 OrderItem 没有 priceamount 值。

要验证哪些 OrderItem 条目没有价格,请执行 OrderItem.where(price: nil);对于金额做 OrderItem.where(amount: nil)

要将这些 nil prices/amounts 视为 0,请将您的代码更改为以下内容:

def total
  order_items.map{ |oi| (oi.price || 0) * (oi.amount || 0) }.sum
end

错误来自这个花絮:

n.price * n.amount

Ruby 试图在 n.price 上调用 * 方法,但 n.price 正在返回 nil,而 nil 没有上面定义了一个 * 方法,所以它会爆炸 "undefined method `*' for nil:NilClass"

简而言之,它不能乘以 nil,它通常只能对类似数字或类似字符串的值进行乘法运算。

如果您想防止订单商品的价格为零,您可以添加模型验证:

class OrderItem
  validates_numericality_of :price, greater_than_or_equal_to: 0

或者您可以更改计算方法以强制使用安全值:

order_items.inject(0) { |sum, n| (n.price || 0) * (n.amount || 1) + sum }