small medium large xlarge

Rassdamon_pragsmall
06 Apr 2010, 17:07
Ricardo (3 posts)

I am testing the examples from Chapter “Active Support”, the section “Enumerations and Arrays”. In the example ~~~ total_orders = Order.find(:all).sum {|order| order.value } ~~~ , since the Order model has not the value field, I am trying with the LineItem model:

I have loaded some orders and line_items…

    p1=Product.find(:first, :conditions=>"title='Pragmatic Project Automation'")
    p2=Product.find(:first, :conditions=>"title='Pragmatic Version Control'")
    p3=Product.find(:first, :conditions=>"title='Pragmatic Unit Testing (C#)'")

    o1=Order.create(:name => 'client 001', :address => 'address 001', :email => '001@g.com', :pay_type => 'check')
     li=LineItem.new(:order=>o1, :product=>p1, :quantity=>2,:total_price=>2*p1.price)
     li.save
     li=LineItem.new(:order=>o1, :product=>p2, :quantity=>3,:total_price=>3*p2.price)
     li.save
     li=LineItem.new(:order=>o1, :product=>p3, :quantity=>4,:total_price=>4*p3.price)
     li.save
    o2=Order.create(:name => 'client 002', :address => 'address 002', :email => '002@g.com', :pay_type => 'cc')
     li=LineItem.new(:order=>o2, :product=>p1, :quantity=>2,:total_price=>2*p1.price)
     li.save
     li=LineItem.new(:order=>o2, :product=>p2, :quantity=>3,:total_price=>3*p2.price)
     li.save
     li=LineItem.new(:order=>o2, :product=>p3, :quantity=>4,:total_price=>4*p3.price)
     li.save

If I sum the total_price of all the line_items, it works …

lis = LineItem.find(:all)
lis.sum{|li| li.total_price}
     #=> #<BigDecimal:7e83580,0.125E4',4(12)>

But if I sum the total_price of just one order, it doesn’t work …

order=Order.find(:first)  #=> #<Order id:i ...>
order.line_items.size     #=> 3
lis = order.line_items

lis.sum{|li| li.total_price}
       #=> ArgumentError: wrong number of arguments (1 for 2)
       # ... from .../active_record/associations/association_collection.rb:378: in 'calculate'

Would you please explain what is wrong here?

Thanks a lot.

Samr_small_pragsmall
08 Apr 2010, 14:57
Sam Ruby (634 posts)

There are two methods called sum, that are similar yet behave differently.

Enumerable#sum will calculate a sum of the elements (in this case of an Array):

http://api.rubyonrails.org/classes/Enumerable.html#M002571

AssociationsCollections has a method called sum that is designed to push this calculation down to the database (which generally is both faster and uses less memory):

http://api.rubyonrails.org/classes/ActiveRecord/Calculations/ClassMethods.html#M002191

If you have an association collection and want to use enumerable methods on it, simply convert it to an array first:

@lis.to_a.sum { li li.total_price}@
You must be logged in to comment