views:

35

answers:

2

I'm trying total up all "amount" columns with a definition in the model like so:

  def self.total
    self.all.collect(&:amount).sum
  end

With that, "Recipe.total" works as expected. However, I'm using a plugin that passes "Recipe.find(:all)", and I can't seem to pass that to the method to find the total. That is:

Recipe.find(:all).total # doesn't work

Is there a way to define the method in my model differently to make Recipe.find(:all).total work like Recipe.total?

+2  A: 

Check out the Calculation Module

It has methods for: sum,average,count, etc ...

Its baked into ActiveRecord.

So you would want to write:

Recipe.sum(:total)

Have fun!

Jonathan
Thanks so much Jonathan. The plugin passes me a Recipe.find(:all), so would there also be a way to make Recipe.find(:all).sum(:total) work too?
sjsc
+4  A: 

You can write your method as:

def self.total
  self.sum(:amount)
end

And then you can use it also with named scopes:

Recipe.total # without any scopes
Recipe.my_custom_named_scope.total # with your custom named scope

Another variant is to override find method for that model:

def self.find(*args)
  result = super
  if args[0] && args[0] == :all
    def result.total
      self.sum(&:amount)
    end
  end
  result
end

Then you get exactly what you want, you'll be able to write Recipe.find(:all).total.

lest
Thanks so much lest. Is there also a way to make Recipe.find(:all).total work as well, or am I out of luck?
sjsc
I've updated my solution
lest
Thank you lest for the great answer! :)
sjsc