diff options
author | Ryan Kerr <leboshi@gmail.com> | 2019-03-30 00:35:16 -0400 |
---|---|---|
committer | Ryan Kerr <leboshi@gmail.com> | 2019-03-30 00:37:08 -0400 |
commit | 2e3bba3e3af8c41e833cced61f0449ad73c947cc (patch) | |
tree | 40b89928e1a3d8463584ae293ea52e087aa806fb /activerecord/test | |
parent | 4e076b03b6312b928a845f9a31288d10d7243338 (diff) | |
download | rails-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')
-rw-r--r-- | activerecord/test/cases/associations/has_many_through_associations_test.rb | 18 |
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 } } |