30bcacccb1c7fa2b577b905a2128027f

I have an Asset model in a Real Estate app
What is the best way to join all named_scope(asset_params) (lines
27..34) to line 36
Thanks
Erez

class Asset < ActiveRecord::Base
	belongs_to :account
	belongs_to :asset_type
	belongs_to :deal_type
	belongs_to :neighborhood
	belongs_to :settlement
	belongs_to :user
	named_scope :showeb, :conditions => {:showeb => 2}
	named_scope :ordered,  :order => 'created_at DESC'
	named_scope :demo, :conditions => {:demo => 1}
	named_scope :image144, :conditions => ["image_list != ?", "null"]
	named_scope :slideshow, :conditions => ["slideshow != ?", "null"]
	named_scope :status, :conditions => {:status => 2}
	named_scope :price_from, lambda {|*args| {:conditions => ["price_shekel >=?", (args.first || 0)]} }
	named_scope :price_to, lambda {|*args| {:conditions => ["price_shekel <=?", (args.first || 9999999999)]} }
	named_scope :rooms_from, lambda {|*args| {:conditions => ["rooms >=?", (args.first || 0)]} }
	named_scope :rooms_to, lambda {|*args| {:conditions => ["rooms <=?", (args.first || 9999)]} }
	named_scope :settlement_filter, lambda { |settlement_ids| {:conditions => {:settlement_id => settlement_ids.to_i} } }  
	named_scope :neighborhood_filter, lambda { |neighborhood_ids| {:conditions => ["neighborhood_id = ?", neighborhood_ids]} }  
	named_scope :assettype_filter, lambda { |assettype_ids| {:conditions => ["assettype_id = ?", assettype_ids]} }
	named_scope :dealtype_filter, lambda { |dealtype_ids| {:conditions => ["dealtype_id = ?", dealtype_ids]} } 
			
	def self.search(asset_params, page, records)
		main = showeb.ordered.demo.image144.slideshow.status
		if asset_params
			#asset_params = User input from advanced search form
			settlement_conditions = settlement_filter(asset_params[:settlement_id]) if asset_params[:settlement_id]
			neighborhood_conditions = neighborhood_filter(asset_params[:neighborhood_id]) if asset_params[:neighborhood_id]
			assettype_conditions = assettype_filter(asset_params[:assettype_id]) if asset_params[:assettype_id]
			dealtype_conditions = dealtype_filter(asset_params[:dealtype_id]) if asset_params[:dealtype_id]
			price_from_conditions = price_from(asset_params[:pr_from]) if asset_params[:pr_from]
			price_to_conditions = price_to(asset_params[:pr_to]) if asset_params[:pr_to]
			rooms_from_conditions = rooms_from(asset_params[:rm_from]) if asset_params[:rm_from]
			rooms_to_conditions = rooms_to(asset_params[:rm_to]) if asset_params[:rm_to]
			
			<[Join all relevant named scopes according to User input ]>
			
			main.< insert relevant named scopes >.paginate(:all, :page => page, :per_page => records)
		else 
			main.paginate(:all, :page => page, :per_page => records)
		end
	end
end

Refactorings

No refactoring yet !

7f00244a6387413b37ee449f234ec045

Marc-Andre

March 17, 2009, March 17, 2009 15:45, permalink

No rating. Login to rate!

I'd use a naming convention, so that a parameter 'xyz' corresponds to a named_scope 'xyz_form_filter', for instance.
I didn't include any error checking, you'll get a NoMethodError thrown if the right form filter doesn't exist.
This gives:

class Asset < ActiveRecord::Base
  belongs_to :account
  belongs_to :asset_type
  belongs_to :deal_type
  belongs_to :neighborhood
  belongs_to :settlement
  belongs_to :user
  named_scope :showeb, :conditions => {:showeb => 2}
  named_scope :ordered,  :order => 'created_at DESC'
  named_scope :demo, :conditions => {:demo => 1}
  named_scope :image144, :conditions => ["image_list != ?", "null"]
  named_scope :slideshow, :conditions => ["slideshow != ?", "null"]
  named_scope :status, :conditions => {:status => 2}
  named_scope :pr_from_form_filter, lambda {|*args| {:conditions => ["price_shekel >=?", (args.first || 0)]} }
  named_scope :pr_to_form_filter, lambda {|*args| {:conditions => ["price_shekel <=?", (args.first || 9999999999)]} }
  named_scope :rm_from_form_filter, lambda {|*args| {:conditions => ["rooms >=?", (args.first || 0)]} }
  named_scope :rm_to_form_filter, lambda {|*args| {:conditions => ["rooms <=?", (args.first || 9999)]} }
  named_scope :settlement_id_form_filter, lambda { |settlement_ids| {:conditions => {:settlement_id => settlement_ids.to_i} } }  
  named_scope :neighborhood_id_form_filter, lambda { |neighborhood_ids| {:conditions => ["neighborhood_id = ?", neighborhood_ids]} }  
  named_scope :assettype_id_form_filter, lambda { |assettype_ids| {:conditions => ["assettype_id = ?", assettype_ids]} }
  named_scope :dealtype_id_form_filter, lambda { |dealtype_ids| {:conditions => ["dealtype_id = ?", dealtype_ids]} } 
  
  def self.search(asset_params, page, records)
    main = showeb.ordered.demo.image144.slideshow.status
    asset_params.each do |key, value|
      main = main.send(:"#{key.to_s}_form_filter", value)
    end if asset_params
    main.paginate(:all, :page => page, :per_page => records)
  end
end
30bcacccb1c7fa2b577b905a2128027f

Erez Ben Shoham

March 17, 2009, March 17, 2009 21:18, permalink

No rating. Login to rate!

Hi Andre,
Thanks for your code
I found on Ryan Bates railscasts.com this
http://railscasts.com/episodes/112-anonymous-scopes

class Asset < ActiveRecord::Base
	belongs_to :account
	belongs_to :asset_type
	belongs_to :deal_type
	belongs_to :neighborhood
	belongs_to :settlement
	belongs_to :user
	named_scope :showeb, :conditions => {:showeb => 2}
	named_scope :ordered,  :order => 'created_at DESC'
	named_scope :demo, :conditions => {:demo => 1}
	named_scope :image144, :conditions => ["image_list != ?", "null"]
	named_scope :slideshow, :conditions => ["slideshow != ?", "null"]
	named_scope :status, :conditions => {:status => 2}
	named_scope :group_settlements, :group => :settlement_id
	named_scope :group_neighborhoods, :group => :neighborhood_id
	named_scope :group_assettypes, :group => :assettype_id
						
	def self.search(asset_params, page, records)
		if asset_params
			scope = scoped({}) 
			scope = scope.conditions "settlement_id = ?", asset_params[:settlement_id] unless asset_params[:settlement_id].blank?
			scope = scope.conditions "neighborhood_id = ?", asset_params[:neighborhood_id] unless asset_params[:neighborhood_id].blank?
			scope = scope.conditions "assettype_id = ?", asset_params[:assettype_id] unless asset_params[:assettype_id].blank?
			scope = scope.conditions "dealtype_id = ?", asset_params[:dealtype_id] unless asset_params[:dealtype_id].blank?
			scope = scope.conditions "price_shekel >= ?", asset_params[:pr_from] unless asset_params[:pr_from].blank?
			scope = scope.conditions "price_shekel <= ?", asset_params[:pr_to] unless asset_params[:pr_to].blank?
			scope = scope.conditions "rooms >= ?", asset_params[:rm_from] unless asset_params[:rm_from].blank?
			scope = scope.conditions "rooms <= ?", asset_params[:rm_to] unless asset_params[:rm_to].blank?
			
			scope.showeb.ordered.demo.image144.slideshow.status.paginate(:all, :page => page, :per_page => records)
		
		else 
			showeb.ordered.demo.image144.slideshow.status.paginate(:all, :page => page, :per_page => records)
		end
	end

# file - /config/initializers/global_named_scopes.rb
class ActiveRecord::Base
	named_scope :conditions, lambda	{ |*args| {:conditions => args} }
end
F1e3ab214a976a39cfd713bc93deb10f

Tj Holowaychuk

March 18, 2009, March 18, 2009 00:58, permalink

No rating. Login to rate!

Like @Marc mentioned its almost always a good practice to utilize names that you have been using programmatically already, it will bite you in the ass if you dont normalize these things, and prevent a lot of automation

Your refactoring





Format Copy from initial code

or Cancel