Topic: I need some help, please

I have the following code snippet - the function self.find_by_filters needs some work... And by some I mean more than some. Basically it's find that filters by a lot of attributes.

At the moment I'm basically checking if a param was sent and adding it to a conditions array. At the moment it's overly verbose and I am sure that it could be done better. Any pointers would be greatly appreciated.

class Project < ActiveRecord::Base
  attr_accessible :title, :supplier_id, :client_id, :completed_at, :due_at,
      :rate_per_hour, :tasks_attributes, :feature_in_portfolio, :state, :position
  
  STATES = ['development', 'waiting on supplier', 'complete']
  
  has_many :timesheets
  has_many :payments
  has_many :tasks
  belongs_to :supplier, :class_name => "Company"
  belongs_to :client, :class_name => "Company"
  
  validates_presence_of :title, :supplier_id, :client_id, :rate_per_hour, :position, :state
  validates_length_of :title, :in => 1..256
  validates_numericality_of :rate_per_hour, :position
  validates_uniqueness_of :title, :scope => [:supplier_id, :client_id]
  validates_inclusion_of :feature_in_portfolio, :in => [true, false]
  validates_inclusion_of :state, :in => self::STATES
  
  accepts_nested_attributes_for :tasks, :allow_destroy => true,
      :reject_if => proc { |attrs| attrs.all? { |k, v| v.blank? } }
    
  default_scope :order => 'due_at ASC'
  
  def self.find_by_filters(params)
    conditions = []
    
    if params[:featured] == 'true'
      conditions << ["feature_in_portfolio = ?", true]
    end
    if params[:featured] == 'false'
      conditions << ["feature_in_portfolio = ?", false]
    end
    
    if params[:state] && self::STATES.include?(params[:state].downcase)
      conditions << ["state = ?", params[:state]]
    end
    
    # http://railsforum.com/viewtopic.php?id=24792
    conditions = ( conditions.empty? ? nil : [conditions.transpose.first.join(' AND '), *conditions.transpose.last] )
    
    order = params[:order] ? params[:order] : 'created_at DESC'
    limit = params[:limit] ? params[:limit] : 10
    
    find(:all, :conditions => conditions, :order => order, :limit => limit, :include => [:supplier, :client])
  end
end

Re: I need some help, please

Not sure there is a better solution, as you are doing some defensive coding in there (which is good) as well. But we could certainly DRY it up a bit.

if params[:featured] == 'true'
  conditions << ["feature_in_portfolio = ?", true]
end
if params[:featured] == 'false'
  conditions << ["feature_in_portfolio = ?", false]
end

could reduce to

conditions << ["feature_in_portfolio = ?", params[:featured] == 'true']

and

if params[:state] && self::STATES.include?(params[:state].downcase)
  conditions << ["state = ?", params[:state]]
end

to

conditions << ["state = ?", params[:state]] if params[:state] && self::STATES.include?(params[:state].downcase)

although that last one is largely a matter of taste and your opinion of statement modifiers...