class Store < ActiveRecord::Base
has_many :promos
def promos
Promo.for_store(self)
end
def promos?
promos.count > 0
end
end
class Promo < ActiveRecord::Base
belongs_to :store
def self.for_store(store=nil, limit=4)
return find(:all, :conditions => ["promos.store_id IS NULL"], :limit => limit) if store.nil?
find(:all, :conditions => ["promos.store_id = ? or promos.store_id IS NULL", store.id], :limit => limit)
end
end
Refactorings
No refactoring yet !
arvanasse
June 8, 2010, June 08, 2010 14:51, permalink
Your code does not seem to match your description. As coded, #promos (instance method override) will always call #for_store with an instance of store so you will only get the promos directly assigned to the store. The main question to understand is how to choose between 'default' promos that belong to every store and the promos assigned to a specific store. Should they be mixed? That is, should you ask for promos and get both 'default' and assigned promos? Should you only get 'default' promos when there are no assigned ones?
Here's an idea or two based on moving the logic of the custom method into (chainable) named_scopes.
class Store < ActiveRecord::Base
has_many :promos
# returns a mix of default and assigned promos
def current_promos
promos.recent(4).for_store(self)
end
# returns either default or assigned promos
def active_promos
promos? ? promos : Promo.recent(4).default_promos
end
def promos?
promos.count > 0
end
end
class Promo < ActiveRecord::Base
belongs_to :store
named_scope :recent, lambda{|limit| { :order => 'id desc', :limit => limit} }
named_scope :for_store, lambda{|store| {:conditions => {:store_id => [nil, store.id]} } }
named_scope :default_promos, :conditions => {:store_id => nil}
end
Store has many Promos. Promos belong to Store. But I also want default Promos (without a Store) to belong to each Store and be included in the association's find. I wrote a custom 'for_store' finder-type method and overrode the Store.promos reader with it. Is there a cleaner way to do this in Rails?