chrisan
chrisan

Reputation: 4282

How can you conditionally build an ActiveRecord Query in Rails?

I'm trying to build a search results page in my rails app (still a noob) and I can't figure out how to build a query the rails way.

For example, if no parameters are present I want to return all results. If the user passes 1 to n optional parameters in the search form I want to add them to the query.

Next if they have a sort specified "price desc" or "year_built desc" or even a combination of both.

Finally use will_paginate to separate the results

# default to all listings
@listings = Mls.all

@listings.where("listing_price > ?", params[:listing_price]) unless params[:listing_price].blank?
# ... bunch of other search options ...
@listings.where("property_type = ?", params[:property_type]) unless params[:property_type].blank?

# order
@listings.order("some order by param") if some sort param
@listings.order("some order by param") if some other sort param

# paginate results
@listings.paginate(:page => params[:page])

Is there a "Rails" way of doing this?

Upvotes: 16

Views: 20180

Answers (3)

Tim Kozak
Tim Kozak

Reputation: 4182

Here is my scope examples, it will query if array is present

scope :tagged_one_of, -> (tags) { tags ? where("tags && ARRAY[?]::varchar[]", tags) : all }
scope :tagged_all_of, -> (tags) { tags ? where("tags @> ARRAY[?]::varchar[]", tags) : all }

example

Product.where(filter).where(sub_filter).tagged_one_of(tags_array)

More about scopes [here]

Upvotes: 0

Andrea Singh
Andrea Singh

Reputation: 1613

Have you seen the (revised) Railscasts episode on advanced searches? Here is the link: http://railscasts.com/episodes/111-advanced-search-form-revised

The basic idea is to create a Search resource that will process the search params sent in through the form and in the background searches over the model in question (in your case Mls)

That way, instead of checking in the controller for the presence of certain parameters (e.g. params[:listing_price]) you could handle the conditions in your Search model (models/search.rb):

def find_listings
  listings = Mls.order(:name)
  listings = listings.where("listing_price > ?", listing_price) if listing_price.present?
  # ... more condition checking
  listings
end

Upvotes: 30

dimuch
dimuch

Reputation: 12818

A couple of links:

Using third-party gems (metasearch)

Code from scratch

Upvotes: 0

Related Questions