Rails has_many:nil的未定义方法`*':NilClass

时间:2015-01-22 16:46:27

标签: ruby-on-rails ruby-on-rails-4

我定义了一个订单有多个订单商品的关系:

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 *&#39;对于nil:NilClass):`

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

实际上,如果我在此方法中添加了一些我试图访问任何订单商品属性的行,请说order_items[0].price我很中心地收到错误。

我不知道为什么会这样。

我的定义与ShoppingCartShoppingCartItems完全相同,但没有遇到此问题。

此外,我正在开发的订单和订单商品类与我之前使用Rails 3.2.9进行的项目非常相似,并且工作正常。

我该怎么办?

2 个答案:

答案 0 :(得分:1)

您的OrderItem没有priceamount值。

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

要将这些nil价格/金额视为0,请将您的代码更改为以下内容:

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

答案 1 :(得分:0)

错误来自这个花絮:

n.price * n.amount

Ruby试图在*上调用n.price方法,但n.price正在返回nilnil没有*在它上面定义的方法,所以它会用&#34;未定义的方法`*&#39;为零:NilClass&#34;

简而言之,它不能乘以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 }