mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Merge pull request #10538 from neerajdotname/3882
scope_chain should not be mutated for other reflections
This commit is contained in:
commit
828134b756
9 changed files with 65 additions and 1 deletions
|
@ -1,3 +1,16 @@
|
|||
* `scope_chain` should not be mutated for other reflections.
|
||||
|
||||
Currently `scope_chain` uses same array for building different
|
||||
`scope_chain` for different associations. During processing
|
||||
these arrays are sometimes mutated and because of in-place
|
||||
mutation the changed `scope_chain` impacts other reflections.
|
||||
|
||||
Fix is to dup the value before adding to the `scope_chain`.
|
||||
|
||||
Fixes #3882.
|
||||
|
||||
*Neeraj Singh*
|
||||
|
||||
* Prevent the inversed association from being reloaded on save.
|
||||
|
||||
Fixes #9499.
|
||||
|
|
|
@ -574,7 +574,7 @@ module ActiveRecord
|
|||
# Add to it the scope from this reflection (if any)
|
||||
scope_chain.first << scope if scope
|
||||
|
||||
through_scope_chain = through_reflection.scope_chain
|
||||
through_scope_chain = through_reflection.scope_chain.map(&:dup)
|
||||
|
||||
if options[:source_type]
|
||||
through_scope_chain.first <<
|
||||
|
|
|
@ -18,6 +18,11 @@ require 'models/subscription'
|
|||
require 'models/tag'
|
||||
require 'models/sponsor'
|
||||
require 'models/edge'
|
||||
require 'models/hotel'
|
||||
require 'models/chef'
|
||||
require 'models/department'
|
||||
require 'models/cake_designer'
|
||||
require 'models/drink_designer'
|
||||
|
||||
class ReflectionTest < ActiveRecord::TestCase
|
||||
include ActiveRecord::Reflection
|
||||
|
@ -227,6 +232,17 @@ class ReflectionTest < ActiveRecord::TestCase
|
|||
assert_equal expected, actual
|
||||
end
|
||||
|
||||
def test_scope_chain_does_not_interfere_with_hmt_with_polymorphic_case
|
||||
@hotel = Hotel.create!
|
||||
@department = @hotel.departments.create!
|
||||
@department.chefs.create!(employable: CakeDesigner.create!)
|
||||
@department.chefs.create!(employable: DrinkDesigner.create!)
|
||||
|
||||
assert_equal 1, @hotel.cake_designers.size
|
||||
assert_equal 1, @hotel.drink_designers.size
|
||||
assert_equal 2, @hotel.chefs.size
|
||||
end
|
||||
|
||||
def test_nested?
|
||||
assert !Author.reflect_on_association(:comments).nested?
|
||||
assert Author.reflect_on_association(:tags).nested?
|
||||
|
|
3
activerecord/test/models/cake_designer.rb
Normal file
3
activerecord/test/models/cake_designer.rb
Normal file
|
@ -0,0 +1,3 @@
|
|||
class CakeDesigner < ActiveRecord::Base
|
||||
has_one :chef, as: :employable
|
||||
end
|
3
activerecord/test/models/chef.rb
Normal file
3
activerecord/test/models/chef.rb
Normal file
|
@ -0,0 +1,3 @@
|
|||
class Chef < ActiveRecord::Base
|
||||
belongs_to :employable, polymorphic: true
|
||||
end
|
4
activerecord/test/models/department.rb
Normal file
4
activerecord/test/models/department.rb
Normal file
|
@ -0,0 +1,4 @@
|
|||
class Department < ActiveRecord::Base
|
||||
has_many :chefs
|
||||
belongs_to :hotel
|
||||
end
|
3
activerecord/test/models/drink_designer.rb
Normal file
3
activerecord/test/models/drink_designer.rb
Normal file
|
@ -0,0 +1,3 @@
|
|||
class DrinkDesigner < ActiveRecord::Base
|
||||
has_one :chef, as: :employable
|
||||
end
|
6
activerecord/test/models/hotel.rb
Normal file
6
activerecord/test/models/hotel.rb
Normal file
|
@ -0,0 +1,6 @@
|
|||
class Hotel < ActiveRecord::Base
|
||||
has_many :departments
|
||||
has_many :chefs, through: :departments
|
||||
has_many :cake_designers, source_type: 'CakeDesigner', source: :employable, through: :chefs
|
||||
has_many :drink_designers, source_type: 'DrinkDesigner', source: :employable, through: :chefs
|
||||
end
|
|
@ -787,6 +787,22 @@ ActiveRecord::Schema.define do
|
|||
t.string 'from'
|
||||
end
|
||||
|
||||
create_table :hotels, force: true do |t|
|
||||
end
|
||||
create_table :departments, force: true do |t|
|
||||
t.integer :hotel_id
|
||||
end
|
||||
create_table :cake_designers, force: true do |t|
|
||||
end
|
||||
create_table :drink_designers, force: true do |t|
|
||||
end
|
||||
create_table :chefs, force: true do |t|
|
||||
t.integer :employable_id
|
||||
t.string :employable_type
|
||||
t.integer :department_id
|
||||
end
|
||||
|
||||
|
||||
except 'SQLite' do
|
||||
# fk_test_has_fk should be before fk_test_has_pk
|
||||
create_table :fk_test_has_fk, :force => true do |t|
|
||||
|
|
Loading…
Reference in a new issue