TheJKFever
TheJKFever

Reputation: 705

Rails custom query based on params

I have zero or many filter params being sent from a json request. the params may contain:

params[:category_ids"]
params[:npo_ids"]

etc.

I am trying to retreive all Projects from my database with the selected ids. Here is what I have currently:

def index
    if params[:category_ids].present? || params[:npo_ids].present?
        @conditions = []
        @ids = []
        if params["category_ids"].present?
            @conditions << '"category_id => ?"'
            @ids << params["category_ids"].collect{|x| x.to_i}
        end
        if params["npo_ids"].present?
            @conditions << '"npo_id => ?"'
            @ids << params["npo_ids"].collect{|x| x.to_i}
        end
        @conditions = @ids.unshift(@conditions.join(" AND "))
        @projects = Project.find(:all, :conditions => @conditions)
    else ...

This really isn't working, but hopefully it gives you an idea of what I'm trying to do.

How do I filter down my activerecord query based on params that I'm unsure will be there.

Maybe I can do multiple queries and then join them... Or maybe I should put a filter_by_params method in the Model...?

What do you think is a good way to do this?

Upvotes: 0

Views: 845

Answers (2)

TheJKFever
TheJKFever

Reputation: 705

I solved this. here's my code

def index
    if params[:category_ids].present? || params[:npo_ids].present?
        @conditions = {}
        if params["category_ids"].present?
            @conditions["categories"] = {:id => params["category_ids"].collect{|x| x.to_i}}
        end
        if params["npo_ids"].present?
            @conditions["npo_id"] = params["npo_ids"].collect{|x| x.to_i}
        end
        @projects = Project.joins(:categories).where(@conditions)
    else

basically it stored the .where conditions in @conditions, which looks something like this when there's both categories and npos:

{:categories => {:id => [1,2,3]}, :npo_id => [1,2,3]}

Then inserting this into

Project.joins(:categories).where(@conditions)

seems to work.

If you're filtering on a has_many relationship, you have to join. Then after joining, make sure to call the specific table you're referring to by doing something like this:

:categories => {:id => [1,2,3]}

Upvotes: 2

house9
house9

Reputation: 20614

In rails 3 and above you build queries using ActiveRelation objects, no sql is executed until you try to access the results, i.e.

query = Project.where(is_active: true)
# no sql has been executed
query.each { |project| puts project.id }
# sql executed when the first item is accessed

The syntax you are using looks like rails 2 style; hopefully you are using 3 or above and if so you should be able to do something like

query = Project.order(:name)
query = query.where("category_id IN (?)", params[:category_ids]) if params[:category_ids].present?
query = query.where("npo_ids IN (?)", params[:npo_ids]) if params[:npo_ids].present?

@projects = query    

Upvotes: 2

Related Questions