22

Is there a way to add callbacks for when an item is added to a habtm relationship?

For example, I have the following two models, User and Role:

# user.rb
class User; has_and_belongs_to_many :roles; end

 

# role.rb
class Role; has_and_belongs_to_many :users; end

I want to add a callback to the << method (@user << @role), but I can't seem to find an ActiveRecord callback because there is no model for the join table (because its a true habtm).

I'm aware that I could write a method like add_to_role(role), and define everything in there, but I'd prefer to use a callback. Is this possible?

sethvargo
  • 26,739
  • 10
  • 86
  • 156

1 Answers1

36

Yes there is:

class User < AR::Base
  has_and_belongs_to_many :roles, 
    :after_add => :tweet_promotion, 
    :after_remove => :drink_self_stupid

private

  def tweet_promotion
    # ...
  end

  def drink_self_stupid
    # ...
  end
end

Look for 'Association callbacks' on this page for more: http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

Alan Peabody
  • 3,507
  • 1
  • 22
  • 26
  • does it matter on which side of the relation do I add the callback, or is it the same?? – zeacuss May 29 '12 at 09:00
  • I just tried this with Rails 3.2.8 and it sadly mattered, on which side you add those callbacks. What is your experience? – Raul Pinto Sep 27 '12 at 13:27
  • For anyone stumbling on this now, yes it matters. That's the trap I fell into. See this answer to understand https://stackoverflow.com/questions/56951926/rails-5-2-association-callbacks-not-firing-on-before-add-or-before-remove?noredirect=1&lq=1 – rmcsharry Jul 25 '19 at 10:39
  • For the ones that were stuck with the `wrong number of arguments (given 1, expected 0)` error, need to include the arg in the private methods called from the callbacks, as it's specified here https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#label-Association+callbacks – Felipe Funes Oct 12 '22 at 18:02
  • the record that is being added or removed, can be passed as a parameter to the callback function. In the above case, `tweet_promotion` can be passed the role record when `role` is added/removed for a `user` record in HABTM, function signature will look like `tweet_promotion(role)`. The same can be done for the opposite direction. – Masroor Oct 30 '22 at 19:25