aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test/cases/associations
diff options
context:
space:
mode:
authorRyan Kerr <leboshi@gmail.com>2019-03-30 00:35:16 -0400
committerRyan Kerr <leboshi@gmail.com>2019-03-30 00:37:08 -0400
commit2e3bba3e3af8c41e833cced61f0449ad73c947cc (patch)
tree40b89928e1a3d8463584ae293ea52e087aa806fb /activerecord/test/cases/associations
parent4e076b03b6312b928a845f9a31288d10d7243338 (diff)
downloadrails-2e3bba3e3af8c41e833cced61f0449ad73c947cc.tar.gz
rails-2e3bba3e3af8c41e833cced61f0449ad73c947cc.tar.bz2
rails-2e3bba3e3af8c41e833cced61f0449ad73c947cc.zip
Fix callbacks on has_many :through associations (#33249)
When adding a child record via a has_many :through association, build_through_record would previously build the join record, and then assign the child record and source_type option to it. Because the before_add and after_add callbacks are called as part of build, however, this caused the callbacks to receive incomplete records, specifically without the other end of the has_many :through association. Collecting all attributes before building the join record ensures the callbacks receive the fully constructed record.
Diffstat (limited to 'activerecord/test/cases/associations')
-rw-r--r--activerecord/test/cases/associations/has_many_through_associations_test.rb18
1 files changed, 18 insertions, 0 deletions
diff --git a/activerecord/test/cases/associations/has_many_through_associations_test.rb b/activerecord/test/cases/associations/has_many_through_associations_test.rb
index 67e013c6e0..fa540c9dab 100644
--- a/activerecord/test/cases/associations/has_many_through_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb
@@ -1474,6 +1474,24 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
assert_equal [subscription2], post.subscriptions.to_a
end
+ def test_child_is_visible_to_join_model_in_add_association_callbacks
+ [:before_add, :after_add].each do |callback_name|
+ sentient_treasure = Class.new(Treasure) do
+ def self.name; "SentientTreasure"; end
+
+ has_many :pet_treasures, foreign_key: :treasure_id, callback_name => :check_pet!
+ has_many :pets, through: :pet_treasures
+
+ def check_pet!(added)
+ raise "No pet!" if added.pet.nil?
+ end
+ end
+
+ treasure = sentient_treasure.new
+ assert_nothing_raised { treasure.pets << pets(:mochi) }
+ end
+ end
+
private
def make_model(name)
Class.new(ActiveRecord::Base) { define_singleton_method(:name) { name } }