在Rails 3.2.8应用程序示例中(在Ruby 1.9.3上),有以下简单设置:
class Account < ActiveRecord::Base
has_many :line_items
def subtotal
line_items.sum(&:price)
end
end
class Line_Item < ActiveRecord::Base
belongs_to :product
def price
product.price * time
end
end
account = Account.new
account.line_items.build do |item|
item.years = 4
item.product = Product.last
end
account.subtotal
#=> TypeError: nil can't be coerced into BigDecimal
如上所述,subtotal
方法因转换错误而失败。在subtotal
中,我检查了line_items.class
返回的类型并获得Array
。如果我将subtotal
的定义更新为以下任一项,则该方法有效:
line_items.to_a.sum(&:price)
#=> #<BigDecimal:7ff4d34ca7c8,'0.0',9(36)>
line_items.map(&:price).sum
#=> #<BigDecimal:7ff4d3373b40,'0.0',9(36)>
为什么line_items.sum(&:price)
的初始定义失败?
答案 0 :(得分:0)
这似乎是Rails中的一个错误(至少在3.2.8中)。
在Rails 3.2.8中,has_many
关联动态定义collection.sum
。
虽然这没有反映在A Guide to Active Record Associations中
或ActiveRecord::Associations::ClassMethods API docs;它简要列在“{em>集合关联(一对多/多对多)”下的API中
图表,但没有再次参考。
根据code,它总是会尝试使用SQL sum
来命中数据库。
但是,在此特定实例中,不保存模型。所以什么都没有
在数据库中。
所以要清楚一点:
account.line_items.sum(&:price) # Uses Collection#sum, goes to database
account.line_items.map.sum(&:price) # Uses Enumerable#map then Enumerable#sum
这已记录在issue #7928下;这似乎与issue #5215: "finders and scopes on has_many association on new object incorrectly query db for null foreign keys"有关。