diff options
-rw-r--r-- | activerecord/CHANGELOG.md | 9 | ||||
-rw-r--r-- | activerecord/lib/active_record/associations/through_association.rb | 6 | ||||
-rw-r--r-- | activerecord/test/cases/associations/has_many_through_associations_test.rb | 11 | ||||
-rw-r--r-- | activerecord/test/models/post.rb | 4 | ||||
-rw-r--r-- | activerecord/test/models/reader.rb | 2 |
5 files changed, 30 insertions, 2 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 74f5666de0..9138230b5e 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,12 @@ +* Fixed unexpected behavior for `has_many :through` associations going through a scoped `has_many`. + + If a `has_many` association is adjusted using a scope, and another `has_many :through` + uses this association, then the scope adjustment is unexpectedly neglected. + + Fixes #14537. + + *Jan Habermann* + * `@destroyed` should always be set to `false` when an object is duped. *Kuldeep Aggarwal* diff --git a/activerecord/lib/active_record/associations/through_association.rb b/activerecord/lib/active_record/associations/through_association.rb index ba7d2a3782..f8a85b8a6f 100644 --- a/activerecord/lib/active_record/associations/through_association.rb +++ b/activerecord/lib/active_record/associations/through_association.rb @@ -14,9 +14,11 @@ module ActiveRecord def target_scope scope = super chain.drop(1).each do |reflection| + relation = reflection.klass.all + relation.merge!(reflection.scope) if reflection.scope + scope.merge!( - reflection.klass.all. - except(:select, :create_with, :includes, :preload, :joins, :eager_load) + relation.except(:select, :create_with, :includes, :preload, :joins, :eager_load) ) end scope 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 6675e19dd9..e30577fb49 100644 --- a/activerecord/test/cases/associations/has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb @@ -1116,5 +1116,16 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase club.reload assert_equal [member], club.favourites + + def test_has_many_through_unscope_default_scope + post = Post.create!(:title => 'Beaches', :body => "I like beaches!") + Reader.create! :person => people(:david), :post => post + LazyReader.create! :person => people(:susan), :post => post + + assert_equal 2, post.people.to_a.size + assert_equal 1, post.lazy_people.to_a.size + + assert_equal 2, post.lazy_readers_unscope_skimmers.to_a.size + assert_equal 2, post.lazy_people_unscope_skimmers.to_a.size end end diff --git a/activerecord/test/models/post.rb b/activerecord/test/models/post.rb index 099e039255..629dfe4765 100644 --- a/activerecord/test/models/post.rb +++ b/activerecord/test/models/post.rb @@ -145,6 +145,10 @@ class Post < ActiveRecord::Base has_many :lazy_readers has_many :lazy_readers_skimmers_or_not, -> { where(skimmer: [ true, false ]) }, :class_name => 'LazyReader' + has_many :lazy_people, :through => :lazy_readers, :source => :person + has_many :lazy_readers_unscope_skimmers, -> { skimmers_or_not }, :class_name => 'LazyReader' + has_many :lazy_people_unscope_skimmers, :through => :lazy_readers_unscope_skimmers, :source => :person + def self.top(limit) ranked_by_comments.limit_by(limit) end diff --git a/activerecord/test/models/reader.rb b/activerecord/test/models/reader.rb index 3a6b7fad34..91afc1898c 100644 --- a/activerecord/test/models/reader.rb +++ b/activerecord/test/models/reader.rb @@ -16,6 +16,8 @@ class LazyReader < ActiveRecord::Base self.table_name = "readers" default_scope -> { where(skimmer: true) } + scope :skimmers_or_not, -> { unscope(:where => :skimmer) } + belongs_to :post belongs_to :person end |