From a44253323f52324d8d5e9355faf907aabcabf512 Mon Sep 17 00:00:00 2001 From: Nick Borromeo Date: Sun, 12 Jul 2020 17:40:26 -0700 Subject: [PATCH] Update association callback docs There is an old open issue (https://github.com/rails/rails/issues/14365) saying that callbacks are not triggered when assocations are destroyed. I believe the issue does not represent a bug, but maybe just a small gap in the docs about triggering callbacks when removing associations. This update changes the example of the section to use the `Firm` class. so that we can include an `after_remove`. This also adds a small `Note:` section reminding users on how to destory associations so that callbacks are triggered. --- .../lib/active_record/associations.rb | 36 ++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 4299d757f6..8114a88b1f 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -594,19 +594,27 @@ module ActiveRecord # you can also define callbacks that get triggered when you add an object to or remove an # object from an association collection. # - # class Project - # has_and_belongs_to_many :developers, after_add: :evaluate_velocity + # class Firm < ActiveRecord::Base + # has_many :clients, + # dependent: :destroy, + # after_add: :congratulate_client, + # after_remove: :log_after_remove # - # def evaluate_velocity(developer) - # ... + # def congratulate_client(record) + # # ... + # end + # + # def log_after_remove(record) + # # ... # end - # end # # It's possible to stack callbacks by passing them as an array. Example: # - # class Project - # has_and_belongs_to_many :developers, - # after_add: [:evaluate_velocity, Proc.new { |p, d| p.shipping_date = Time.now}] + # class Firm < ActiveRecord::Base + # has_many :clients, + # dependent: :destroy, + # after_add: [:congratulate_client, -> (firm, record) { firm.log << "after_adding#{record.id}" }], + # after_remove: :log_after_remove # end # # Possible callbacks are: +before_add+, +after_add+, +before_remove+ and +after_remove+. @@ -617,6 +625,18 @@ module ActiveRecord # Similarly, if any of the +before_remove+ callbacks throw an exception, the object # will not be removed from the collection. # + # Note: To trigger remove callbacks, you must use +destroy+ / +destroy_all+ methods. For example: + # + # * firm.clients.destroy(client) + # * firm.clients.destroy(*clients) + # * firm.clients.destroy_all + # + # +delete+ / +delete_all+ methods like the following do *not* trigger remove callbacks: + # + # * firm.clients.delete(client) + # * firm.clients.delete(*clients) + # * firm.clients.delete_all + # # == Association extensions # # The proxy objects that control the access to associations can be extended through anonymous