mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Merge pull request #16314 from zoltankiss/allow-nested-has-many-associations-on-unpersisted-parent-instances
fix nested `has many :through` associations on unpersisted parent instances
This commit is contained in:
commit
027f865fc8
4 changed files with 76 additions and 1 deletions
|
@ -1,3 +1,41 @@
|
|||
* Fix nested `has_many :through` associations on unpersisted parent instances.
|
||||
|
||||
For example, if you have
|
||||
|
||||
class Post < ActiveRecord::Base
|
||||
belongs_to :author
|
||||
has_many :books, through: :author
|
||||
has_many :subscriptions, through: :books
|
||||
end
|
||||
|
||||
class Author < ActiveRecord::Base
|
||||
has_one :post
|
||||
has_many :books
|
||||
has_many :subscriptions, through: :books
|
||||
end
|
||||
|
||||
class Book < ActiveRecord::Base
|
||||
belongs_to :author
|
||||
has_many :subscriptions
|
||||
end
|
||||
|
||||
class Subscription < ActiveRecord::Base
|
||||
belongs_to :book
|
||||
end
|
||||
|
||||
Before:
|
||||
|
||||
If `post` is not persisted, then `post.subscriptions` will be empty.
|
||||
|
||||
After:
|
||||
|
||||
If `post` is not persisted, then `post.subscriptions` can be set and used
|
||||
just like it would if `post` were persisted.
|
||||
|
||||
Fixes #16313.
|
||||
|
||||
*Zoltan Kiss*
|
||||
|
||||
* Fixed inconsistency with `first(n)` when used with `limit()`.
|
||||
The `first(n)` finder now respects the `limit()`, making it consistent
|
||||
with `relation.to_a.first(n)`, and also with the behavior of `last(n)`.
|
||||
|
|
|
@ -68,7 +68,7 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
def foreign_key_present?
|
||||
through_reflection.belongs_to? && !owner[through_reflection.foreign_key].nil?
|
||||
through_reflection.belongs_to_or_through? && !owner[through_reflection.foreign_key].nil?
|
||||
end
|
||||
|
||||
def ensure_mutable
|
||||
|
|
|
@ -504,6 +504,10 @@ module ActiveRecord
|
|||
@association_scope_cache.clear
|
||||
end
|
||||
|
||||
def belongs_to_or_through?
|
||||
belongs_to?
|
||||
end
|
||||
|
||||
def nested?
|
||||
false
|
||||
end
|
||||
|
@ -836,6 +840,10 @@ module ActiveRecord
|
|||
source_reflection.join_scopes(table, predicate_builder) + super
|
||||
end
|
||||
|
||||
def belongs_to_or_through?
|
||||
through_reflection.belongs_to_or_through?
|
||||
end
|
||||
|
||||
def has_scope?
|
||||
scope || options[:source_type] ||
|
||||
source_reflection.has_scope? ||
|
||||
|
|
|
@ -1308,6 +1308,35 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
def test_single_has_many_through_association_with_unpersisted_parent_instance
|
||||
post_with_single_has_many_through = Class.new(Post) do
|
||||
def self.name; "PostWithSingleHasManyThrough"; end
|
||||
has_many :subscriptions, through: :author
|
||||
end
|
||||
post = post_with_single_has_many_through.new
|
||||
post.author = Author.create!(name: "Federico Morissette")
|
||||
book = Book.create!(name: "essays on single has many through associations")
|
||||
post.author.books << book
|
||||
subscription = Subscription.first
|
||||
book.subscriptions << subscription
|
||||
assert_equal [subscription], post.subscriptions.to_a
|
||||
end
|
||||
|
||||
def test_nested_has_many_through_association_with_unpersisted_parent_instance
|
||||
post_with_nested_has_many_through = Class.new(Post) do
|
||||
def self.name; "PostWithNestedHasManyThrough"; end
|
||||
has_many :books, through: :author
|
||||
has_many :subscriptions, through: :books
|
||||
end
|
||||
post = post_with_nested_has_many_through.new
|
||||
post.author = Author.create!(name: "Obie Weissnat")
|
||||
book = Book.create!(name: "essays on nested has many through associations")
|
||||
post.author.books << book
|
||||
subscription = Subscription.first
|
||||
book.subscriptions << subscription
|
||||
assert_equal [subscription], post.subscriptions.to_a
|
||||
end
|
||||
|
||||
private
|
||||
def make_model(name)
|
||||
Class.new(ActiveRecord::Base) { define_singleton_method(:name) { name } }
|
||||
|
|
Loading…
Reference in a new issue