Skip to content

Instantly share code, notes, and snippets.

@cupakromer
Created October 12, 2012 22:24
Show Gist options
  • Save cupakromer/3881956 to your computer and use it in GitHub Desktop.
Save cupakromer/3881956 to your computer and use it in GitHub Desktop.
Rails Bug Issue Draft
class Cart < ActiveRecord::Base
  has_many :line_items

  def total
    line_items.sum(&:price)
  end
end

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

  attr_accessible :amount, :product

  def price
    product.price * amount
  end
end


product = Product.create!(name: 'Ruby shirt', price: 2.25)
cart = Cart.new
cart.line_items.build do |item|
  item.amount = 2
  item.products = product
end

cart.line_items.sum(&:price)
#=> 0

cart.line_items.to_a.sum(&:price)
#=> #<BigDecimal:7ff4d34ca7c8,'0.0',9(36)>

cart.line_items.map(&:price).sum
#=> #<BigDecimal:7ff4d3373b40,'0.0',9(36)>

It seems in (Rails 3.2.8, Ruby 1.9.3) that has_many is creating collection.sum. Though this isn't reflected in A Guide to Active Record Associations or ActiveRecord::Associations::ClassMethods API docs; though it is briefly listed in the "Collection associations (one-to-many / many-to-many)" chart, but not anywhere else in the doc.

According to the code, it will always try to hit the database using a SQL sum. However, in this particular instance, the model isn't saved. So there's nothing in the database. I would think it should pull from the cached copy.

Also, there is the potential where the model is saved, but the collection was modified but not saved yet (i.e. with a build); this could cause un-expected sums.

Line 28 in the code above returns 0 ignoring the built association.

A sample app with the issue reproduced is available here: https://github.com/cupakromer/sum_bug

I've added unit sests are in test/unit/cart_test.rb

To reproduce this issue:

  • Clone this repo
  • Run bundle
  • Run rake
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment