Reputation: 459
I have a number of classes like the below:
class Event < ActiveRecord::Base
include PreventUpdate
has_many :participants, conditions: ...
has_many :venues, conditions: ...
has_many :companies, conditions: ...
end
I have a module that handles prevent_update logic (obj is in past, obj is banned) for the classes, and as part of that it queries the including class for its has_many associations in order to write before_add hooks to those associations.
module PreventUpdate
extend ::ActiveSupport::Concern
included do
self.reflect_on_all_associations(:has_many).each do |assoc|
has_many assoc.name, before_add: :prevent_update
end
end
def prevent_update
#core prevent update logic
end
end
The only problem is that the dynamically added and original has_many statements overwrite each other. Which overwrites which depends on where in the including class the module is included.
Is there any way that the dynamically added and original declarations can "accumulate", i.e. the module's declaration can simply add on to the original without overwriting?
Upvotes: 2
Views: 404
Reputation: 7561
This is untested, but you should be able to just do:
included do
self.reflect_on_all_associations(:has_many).each do |assoc|
assoc.options.merge!(:before_add => :prevent_update)
end
end
This would require that the concern include
come after the has_many
declarations. If you want to do the include
before them, you could add:
module ClassMethods
def modify_associations
self.reflect_on_all_associations(:has_many).each do |assoc|
assoc.options.merge!(:before_add => :prevent_update)
end
end
end
and then:
# ...
has_many :companies, conditions: ...
modify_associations
EDIT
This should work:
included do
self.reflect_on_all_associations(:has_many).each do |assoc|
has_many assoc.name, assoc.options.merge(:before_add => :prevent_update)
end
end
Upvotes: 2