Reputation: 661
I have a number of models that need the same scope. They each have an expiration_date
date field that I want to write a scope against.
To keep things DRY, I'd like to put the scope in a module (in /lib) that I'll extend each model with. However, when I call scope
within the module, the method is undefined.
To work around this, I use class_eval
when the module is included:
module ExpiresWithinScope
def self.extended(base)
scope_code = %q{scope :expires_within, lambda { |number_of_months_from_now| where("expiration_date BETWEEN ? AND ?", Date.today, Date.today + number_of_months_from_now) } }
base.class_eval(scope_code)
end
end
I then do extend ExpiresWithinScope
in my models.
This approach works, but feels a little hackish. Is there a better way?
Upvotes: 3
Views: 2489
Reputation: 10150
You could do something a little cleaner like this, since scope is a public class method:
module ExpiresWithinScope
def self.included(base)
base.scope :expires_within, lambda { |number_of_months_from_now|
base.where("expiration_date BETWEEN ? AND ?",
Date.today,
Date.today + number_of_months_from_now)
}
end
end
and then in your model
include ExpiresWithinScope
Upvotes: 10
Reputation: 21700
With AR3, they finally got somewhere near DataMapper awesomeness, so you can go
module ExpiresWithinScope
def expires_within(months_from_now)
where("expiration_date BETWEEN ? AND ?",
Date.today,
Date.today + number_of_months_from_now)
end
end
You could also try:
module ExpiresWithinScope
def expires_within(months_from_now)
where(:expiration_date => Date.today..(Date.today + number_of_months_from_now))
end
end
But according to the guide, arel can't handle that as well.
Upvotes: 5