Permalink
Browse files

Merge pull request #16314 from zoltankiss/allow-nested-has-many-assoc…

…iations-on-unpersisted-parent-instances

fix nested `has many :through` associations on unpersisted parent instances
  • Loading branch information...
kamipo committed Jan 10, 2018
2 parents 7ccd070 + 1813350 commit 027f865fc8b262d9ba3ee51da3483e94a5489b66
@@ -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 @@ def stale_state
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 @@ def clear_association_scope_cache # :nodoc:
@association_scope_cache.clear
end
def belongs_to_or_through?
belongs_to?
end
def nested?
false
end
@@ -836,6 +840,10 @@ def join_scopes(table, predicate_builder) # :nodoc:
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 @@ def test_incorrectly_ordered_through_associations
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 } }

0 comments on commit 027f865

Please sign in to comment.