In my app we have lists of people that we allow users to filter a
variety of ways. For example, a user might choose 3 filters: Enrolled,
Living and Lives in Wyoming.
To handle this, I’ve been using named scopes. The Person model has
lines like this:
named_scope :enrolled, :conditions => “blah”
named_scope :living, :conditions => “blah”
named_scope :lives_in_state, lambda { |s| {:conditions => [“state
= ?”, s]}}
And then when getting the People to display in the view, I’ll have:
@people = People.enrolled.living.lives_in_state(“WY”).paginate
So far this has worked well because I’m filtering based on pretty
straightforward data requirements.
But now I’m implementing a new filter that relies not on the Person
data, but on a Person instance method.
class Person
def evaluation_score
…logic to determine score
end
end
Say I want to filter people that have an evaluation score of 80 or
higher. How can I integrate this with the named route solution that
I’ve already implemented. What I’d like is to be able to do something
like this:
@people =
People.enrolled.living.lives_in_state(“WY”).evaluation_score_over(80).paginate
Right now I’ve just added a new class method
class Person
def Person.evaluation_score_over(minimum_score)
self.all.reject {|l| l.evaluation_score < minimum_score}
end
def evaluation_score
… logic to determine score
end
end
And this works. But it also breaks the chaining I can do with named
scopes. So if I try this:
People.evaluation_score_over(80).enrolled.living.lives_in_state(“WY”).paginate
it fails. evaluation_score_over returns an array and the array doesn’t
have a method “enrolled”.
Is there a way I can implement the kind of filtering I need to do and
still get all the chaining benefits of named scopes?