Welcome to Working With Rails

 

Discussion Forums

Discuss all things Ruby on Rails with perhaps the web's most vibrant group of Ruby on Rails enthusiasts.
Help with Methods for Multiple objects
12 Posts
Help with Methods for Multiple objects

Richard,

You're right that the example I gave you for passing an array of PhoneCall objects to a class methods to determine the sum is incorrect. I left off one bit. If you take a look at the #sum method for Enumerable (defined in ActiveSupport), you'll see it can take a block. So, my initial suggestion was something like this:

def self.total_cost(phone_calls)
  phone_calls.to_a.sum
end

However, calling #sum on an Array without a block will simply try to add up the elements of the array. The PhoneCall class likely doesn't (and shouldn't) respond to the + operator, so this won't work. Passing a block to #sum allows you to tell it what values you want the sum of. First, it will execute the block on each element of the array, then it will compute the sum of the results. So, this will work:

def self.total_cost(phone_calls)
  phone_calls.to_a.sum { |phone_call| phone_call.cost }
end

Kevin suggested you try using a shorthand syntax that Rails provides by defining the #to_proc method on symbols:

def self.total_cost(phone_calls)
  phone_calls.to_a.sum(&:cost)
end

The last two examples do exactly the same thing, functionally. Whenver you see the block operator (&) applied to a symbol in Rails, it will expand to a block that takes one parameter and returns the result of sending the symbol to that parameter. It does this by calling #to_proc on the symbol, which is standard Ruby behavior for the & operator.

This is all further obfuscated by the fact that I've so far given examples only for the #sum method defined on the Enumerable class by ActiveSupport. Jason has been giving examples for the #sum class method defined for ActiveRecord::Base. The latter is what you want to use for generating the sum for a given colum in the database, using the standard finder options to limit the rows included in the sum. The Enumerable#sum method will allow you to add up most anything else.

Hi Jason Thanks very much for that. Its good to grasp that the context of the use of sum is what defines it. The activesupport methods will com in very handy I think.

Hi Adam,

Thanks for your long and detailed explanation. I am learning so much from my simple question. It just gives me such respect for you guys that have such a detailed understanding of this. If you told me before I started trying to learn this that their was a sum method and a sum method and a sum method and they were all different I would have probably decided to leave it alone! But now I am hooked in and its too late!! Thankyou.

Am I right in thinking it is slightly inefficient to find the objects in the controller first so that I can iterate through them in the view to display one attribute and then effectively find them again with the activesuport sum method to find the sum when all the information that I need is already continued in that array of phonecalls from the original find. So using the total method with the array passed to it should be more efficient with regard to database calls.

I need to work through what I have learned a few times on Monday to make sure I have really understood what I have learned.

My find with conditions returns an array of phonecalls that do not have cost centers assigned to them for a certain period. The cli model is the dialled out line number and so each line number that has not been associated to a cost center has all its phonecalls returned. I would like to display each of the unique cli and the total of its phonecalls cost. So in my array of phonecalls many of them are for the same cli. Could you point me in the direction of how to iterate through the array of calls and identify the unique cli attribute and then the total sum.

That probably makes no sense!

Anyway I figure I am going to need to create a class method with an array passed any tips much appreciated.

Thanks again everybody for your help, the Rails community seems to be one of its greatest attributes.

If anybody is happy to pass their email or skype name to allow me to tap them up occasionally when I get stauck then I would really appreciate it.

Richard

12 Posts
Login to add your message