views:

13

answers:

3

I've got a simple list page with a couple of search filters status which is a simple enumeration and a test query which I want to compare against both the title and description field of my model.

In my controller, I want to do something like this:

def index
  conditions = {}
  conditions[:status] = params[:status] if params[:status] and !params[:status].empty?
  conditions[???] = ["(descr = ? or title = ?)", params[:q], params[:q]] if params[:q] and !params[:q].empty?
  @items = Item.find(:all, :conditions => conditions)
end

Unfortunately, it doesn't look like I can mix the two types of conditions (the hash and the paramatized version). Is there a "Rails Way" of doing this or do I simply have to do something awful like this:

has_status = params[:status] and !params[:status].empty?
has_text = params[:q] and !params[:q].empty?
if has_status and !has_text
   # build paramatized condition with just the status
elsif has_text and !has_status
   # build paramatized condition with just the text query
elsif has_text and has_status
   # build paramatized condition with both
else
   # build paramatized condition with neither
end

I'm migrating from Hibernate and Criteria so forgive me if I'm not thinking of this correctly...

Environment: Rails 2.3.4

A: 
a=[],b=[]
unless params[:status].blank?
  a << "status = ?"
  b << params[:status]
end
unless params[:q].blank?
  a << "(descr = ? or title = ?)"
  b << params[:q] << params[:q]
end
@items = Item.all( :conditions => [a.join(" AND "), b] )
zed_0xff
A: 

A better search on my part turned up something called "named scopes" which looks like is exactly what I'm looking for. I'm about to see if it will work with the will_paginate gem....

Reference: http://edgerails.info/articles/what-s-new-in-edge-rails/2010/02/23/the-skinny-on-scopes-formerly-named-scope/

GSP
It works great with will_paginate. @items = Item.filtered_by_test(params[:query]).paginate(:conditions => conditions)This is my new favorite rails feature!
GSP
A: 

You can mix hash and array conditions using scopes:

hash_conditions = {}
# build hash_conditions

items_scope = Item.scoped(:conditions => hash_conditions)

unless params[:q].blank?
  items_scope = items_scope.scoped(:conditions => ["(descr = ? or title = ?)", params[:q], params[:q]])
end

...

items = items_scope.all

So you can mix and match any types of conditions, and the query will be executed only when you do items_scope.all

Voyta
Just to clarify, is the "scoped" available in Rails 2.x or is it a Rails 3 enhancement?
GSP
It is available since named_scope-s were added - since Rails 2.1.0. It is just a named scope, which is defined for all ActiveRecord classes. See http://apidock.com/rails/ActiveRecord/NamedScope/included/class
Voyta