4

Trying to do a basic filter in rails 3 using the url params. I'd like to have a white list of params that can be filtered by, and return all the items that match. I've set up some scopes (with many more to come):

# in the model:
scope :budget_min, lambda {|min| where("budget > ?", min)}
scope :budget_max, lambda {|max| where("budget < ?", max)}

...but what's the best way to use some, none, or all of these scopes based on the present params[]? I've gotten this far, but it doesn't extend to multiple options. Looking for a sort of "chain if present" type operation.

@jobs = Job.all
@jobs = Job.budget_min(params[:budget_min]) if params[:budget_min]

3 Answers 3

6

I think you are close. Something like this won't extend to multiple options?

query = Job.scoped
query = query.budget_min(params[:budget_min]) if params[:budget_min]
query = query.budget_max(params[:budget_max]) if params[:budget_max]
@jobs = query.all
Sign up to request clarification or add additional context in comments.

1 Comment

perfect - I was missing the Job.scoped
1

Generally, I'd prefer hand-made solutions but, for this kind of problem, a code base could become a mess very quickly. So I would go for a gem like meta_search.

1 Comment

looks interesting, but there's gotta be a simple way that doesn't require a tack on gem
1

One way would be to put your conditionals into the scopes:

scope :budget_max, lambda { |max| where("budget < ?", max) unless max.nil? }

That would still become rather cumbersome since you'd end up with:

Job.budget_min(params[:budget_min]).budget_max(params[:budget_max]) ...

A slightly different approach would be using something like the following inside your model (based on code from here:

class << self
  def search(q)
    whitelisted_params = {
      :budget_max => "budget > ?",
      :budget_min => "budget < ?"
    }

    whitelisted_params.keys.inject(scoped) do |combined_scope, param|
      if q[param].nil?
        combined_scope
      else
        combined_scope.where(whitelisted_params[param], q[param])
      end
    end
  end
end

You can then use that method as follows and it should use the whitelisted filters if they're present in params:

MyModel.search(params)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.