0

I am having what I think is a simple problem chaining two scopes (Rails 3.2.5).

I have a model called Point with fields amount and transaction_date, amongst other. Users get an amount of points for various activities, and they are "available" until used, which happens as part of a transaction, at which point transaction_date is updated, and no longer empty.

So I have a scope like this:

scope :available, where("transaction_date IS NULL OR transaction_date = ''")

and it works great, returning the proper collection of Point objects. So I can do

> Point.available
=> [#<Point id: 123, amount: 22, transaction_date: nil >][#<Point id: 456, amount: 33, transaction_date: nil >]

And if I want to know the sum of available points, I can do

> Point.available.sum("amount")
=> 55

But if I try to make another scope like

scope :available, where("transaction_date IS NULL OR transaction_date = ''")
scope :total_available, available.sum("amount")

I get the error

NoMethodError: undefined method `default_scoped?' for 22:Fixnum

or if I change the scope so it's sum("amount").available I get the error

NoMethodError: undefined method `available' for 55:Fixnum

I can also make the :total_available scope work by adding the condition defined in :available, but that's not very DRY.

What am I missing here?

Tom Harrison
  • 13,533
  • 3
  • 49
  • 77

1 Answers1

5

The expression available.sum gets evaluate straight away so your attempts are equivalent to

scope :total_available, 55

Or

scope :total_available, 55.available

Which is clearly wrong. Personally I'd use a class method for this

def self.total_available
  available.sum(:amount)
end

I think of scopes as a scoped collection: it doesn't make sense to me for scopes to be numbers - for one thing they'd be scopes you couldn't chain other scoped onto

Tom Harrison
  • 13,533
  • 3
  • 49
  • 77
Frederick Cheung
  • 83,189
  • 8
  • 152
  • 174
  • Thanks @Frederick Chung -- Thanks for the explanation of the errors, that helps me understand the failure. I also think your solution is practical and your reasoning for its use logical. However, scopes are implemented in AREL and [documented here](http://guides.rubyonrails.org/active_record_querying.html#calculations) and show a case sort of similar to mine -- chaining used as additional refinement. Maybe my question should be "Is there a right way for Rails?" to use scopes with aggregates like `sum`? – Tom Harrison Jul 11 '12 at 18:48
  • I can see examples there of running calculations on scopes but not of defining a scope that is a calculation – Frederick Cheung Jul 11 '12 at 18:55
  • Yeah, clearly they are a little different than regular scopes. And anyway your solution works almost identically to a scope. – Tom Harrison Jul 11 '12 at 19:36