I have a join model represented by has_many :through with some conditions. Thanks to Jeremy Kemper’s patches (http://dev.rubyonrails.org/changeset/4786), I can add records to the collection. However, since I have a condition on the finders referencing an attribute, I would also like to set that attribute when I add records to the collection. Since Jeremy’s extensions don’t support before_add and after_add, the only solution I found was to add an extension and override the association methods.
Some code:
Here is the first association:
has_many :partner_children,
:class_name => ‘ClientsPartner’,
:foreign_key => ‘partner_id’
Here is what I would like to do:
Role.find(:all).each do |role|
has_many :“children_as_#{role.short_name}”,
:through => :partner_children, :source => :client,
:conditions => ["role_id = ?", role.id],
:before_add => lambda { (set attributes on join model) }
end
And here is what I ended up with:
Role.find(:all).each do |role|
children_as_role_extension = Module.new
children_as_role_extension.module_eval(<<-EOT)
def <<(*records)
records.each do |record|
@owner.partner_children.create(:client => record, :role_id => #{role.id})
end
reload
end
def delete(record)
@owner.partner_children.find(:all, :conditions =>
["client_id = ? and role_id = ?", record.id, #{role.id}]
).each(&:destroy)
reload
end
def clear
@owner.partner_children.find(:all, :conditions =>
["role_id = ?", #{role.id}]
).each(&:destroy)
reload
end
EOT
has_many :“children_as_#{role.short_name}”,
:through => :partner_children, :source => :client,
:conditions => ["role_id = ?", role.id], :extend => children_as_role_extension
end