0

在示例 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)失败?

4

1 回答 1

0

这似乎是 Rails 中的一个错误(至少在 3.2.8 中)。

在 Rails 3.2.8 中,has_many关联是动态定义的collection.sum。虽然这没有反映在A Guide to Active Record AssociationsActiveRecord::Associations::ClassMethods API 文档中;它在“集合关联(一对多/多对多) ”图表下的API中简要列出,但未再次引用。

根据代码,它总是会尝试使用 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

这已记录在问题 #7928下;这似乎与问题 #5215: "finders and scopes on has_many association on new object wrongly query db for null foreign keys" 相关

于 2012-10-15T14:49:18.923 回答