Where to put my ruby class class "meta-generator"?
i have the following:
class ThirdParty < ActiveRecord::Base
# Dynamically adds accessors of the requested kind.
def self.has_many_children_of_kind (kinds=[])
puts 'In generator method'
kinds.each { |k|
n = k.to_s
self.class_eval %{
has_many :#{n}_as_owner, {
:foreign_key => :owner_id,
:class_name => 'ThirdPartiesLink',
:conditions => #{ k!=:third_parties ? "{ :kind => '"+n.singularize+"' }" : 'nil' }
}
has_many :#{n}, {
:through => :#{n}_as_owner,
:source => :owned
开发者_如何学运维 }
}
}
end
# Make dynamic associations of given kinds.
has_many_children_of_kind [ :third_parties, :customers, :suppliers, :contacts ]
end
class ThirdPartiesLink < ActiveRecord::Base
belongs_to :owner, :foreign_key => :owner_id, :class_name => 'ThirdParty'
belongs_to :owned, :foreign_key => :owned_id, :class_name => 'ThirdParty'
# This model has a column named 'kind' for storing the link kind.
end
Everything is working exactly as i expect. The line:
has_many_children_of_kind [ :third_parties, :customers, :suppliers, :contacts ]
Generates:
has_many :third_parties_as_owner, { :foreign_key => :owner_id, :class_name => 'ThirdPartiesLink', :conditions => nil }
has_many :third_parties, { :through => :third_parties_as_owner, :source => :owned }
has_many :customers_as_owner, { :foreign_key => :owner_id, :class_name => 'ThirdPartiesLink', :conditions => { :kind => 'customer' } }
has_many :customers, { :through => :customers_as_owner, :source => :owned }
has_many :suppliers_as_owner, { :foreign_key => :owner_id, :class_name => 'ThirdPartiesLink', :conditions => { :kind => 'supplier' } }
has_many :suppliers, { :through => :suppliers_as_owner, :source => :owned }
has_many :contacts_as_owner, { :foreign_key => :owner_id, :class_name => 'ThirdPartiesLink', :conditions => { :kind => 'contact' } }
has_many :contacts, { :through => :contacts_as_owner, :source => :owned }
However, each time i refresh a page in which the ThirdParty object is used, the line 'In generator method' gets outputed in the console.
i have tried several things: puting the has_many_children_of_kind in my application initializers instead of putting it in the ThirdParty class (i really don't like that, it was more of a test than anything else). In this case, the first display of a page works after the server is restarted, but then if i refresh the page, the generated methods are not found when called on a ThirdParty instance...
What would be the way to make sure the ThirdParty class gets written with the accessors once for all at startup of the server?
Thanks for your time! Pierre.
Edit: The generator method block could also be like this:
kinds.each { |k|
n = k.to_s
has_many("#{n}_as_owner".to_sym, {
:foreign_key => :owner_id,
:class_name => 'ThirdPartiesLink',
:conditions => ( k!=:third_parties ? { :kind => n.singularize } : nil)
}
)
has_many(n.to_sym, {
:through => "#{n}_as_owner".to_sym,
:source => :owned
}
)
}
What is the best? The eval or the latest? i'd say the latest, because no parser / eval is involved, so it's probably a bit faster, right?
A good answer is the one pointed out by MikeOnRails.
精彩评论