mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Merge pull request #35799 from leboshi/master
Fix callbacks on has_many :through associations
This commit is contained in:
commit
aae8fd0e07
3 changed files with 29 additions and 11 deletions
|
@ -1,3 +1,10 @@
|
||||||
|
* Assign all attributes before calling `build` to ensure the child record is visible in
|
||||||
|
`before_add` and `after_add` callbacks for `has_many :through` associations.
|
||||||
|
|
||||||
|
Fixes #33249.
|
||||||
|
|
||||||
|
*Ryan H. Kerr*
|
||||||
|
|
||||||
* Add `ActiveRecord::Relation#extract_associated` for extracting associated records from a relation.
|
* Add `ActiveRecord::Relation#extract_associated` for extracting associated records from a relation.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
|
@ -57,19 +57,12 @@ module ActiveRecord
|
||||||
@through_records[record.object_id] ||= begin
|
@through_records[record.object_id] ||= begin
|
||||||
ensure_mutable
|
ensure_mutable
|
||||||
|
|
||||||
through_record = through_association.build(*options_for_through_record)
|
attributes = through_scope_attributes
|
||||||
through_record.send("#{source_reflection.name}=", record)
|
attributes[source_reflection.name] = record
|
||||||
|
attributes[source_reflection.foreign_type] = options[:source_type] if options[:source_type]
|
||||||
|
|
||||||
if options[:source_type]
|
through_association.build(attributes)
|
||||||
through_record.send("#{source_reflection.foreign_type}=", options[:source_type])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
through_record
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def options_for_through_record
|
|
||||||
[through_scope_attributes]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def through_scope_attributes
|
def through_scope_attributes
|
||||||
|
|
|
@ -1474,6 +1474,24 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
|
||||||
assert_equal [subscription2], post.subscriptions.to_a
|
assert_equal [subscription2], post.subscriptions.to_a
|
||||||
end
|
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
|
private
|
||||||
def make_model(name)
|
def make_model(name)
|
||||||
Class.new(ActiveRecord::Base) { define_singleton_method(:name) { name } }
|
Class.new(ActiveRecord::Base) { define_singleton_method(:name) { name } }
|
||||||
|
|
Loading…
Reference in a new issue