Dynamically create after_add and after_remove callbacks for has_many or habtm?

Is there a way to dynamically add after_add and after_remove to existing has_many or has_and_belongs_to_many ?

For example, suppose I have a User , Thing model, and a UserThingRelationship join UserThingRelationship , and the User model looks something like this:

 class User < ActiveRecord::Base has_many :user_thing_relationships has_many :things, :through => :user_thing_relationships end 

I would like to be able in the module that extends User to add :after_add and :after_remove callbacks to the relation User.has_many(:things, ...) . Ie have something like

 module DoesAwesomeStuff def does_awesome_stuff relationship, callback # or however this can be achieved... after_add(relationship) callback after_remove(relationship) callback end end 

So,

 class User < ActiveRecord::Base has_many :user_thing_relationships has_many :things, :through => :user_thing_relationships does_awesome_stuff :things, :my_callback def my_callback; puts "awesome"; end end 

It is actually the same as

 class User < ActiveRecord::Base has_many :user_thing_relationships has_many :things, :through => :user_thing_relationships, :after_add => :my_callback, :after_remove => :my_callback def my_callback; puts "awesome"; end end 

This can be done quite efficiently for adding after_save , etc. callbacks to the extensible model, since ActiveRecord::Base#after_save is just a class method.

+6
source share
2 answers

I was able to come up with the following using ActiveRecord :: Reflection :

 module AfterAdd def after_add rel, callback a = reflect_on_association(rel) send(a.macro, rel, a.options.merge(:after_add => callback)) end end class User < ActiveRecord::Base extend AfterAdd has_many :user_thing_relationships has_many :things, :through => :user_thing_relationships after_add :things, :my_callback def my_callback puts "Hello" end end 

I do not want to answer my question, so I will not be responsible for the loan if someone can come up with a better solution in the next few days.

+5
source

The simplest would be

 User.after_add_for_things << lambda do |user, thing| Rails.logger.info "#{thing} added to #{user}" end 
+10
source

Source: https://habr.com/ru/post/906705/


All Articles