Merge pull request #10538 from neerajdotname/3882
scope_chain should not be mutated for other reflections
This commit is contained in:
commit
828134b756
@ -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.
|
* Prevent the inversed association from being reloaded on save.
|
||||||
|
|
||||||
Fixes #9499.
|
Fixes #9499.
|
||||||
|
@ -574,7 +574,7 @@ def scope_chain
|
|||||||
# Add to it the scope from this reflection (if any)
|
# Add to it the scope from this reflection (if any)
|
||||||
scope_chain.first << scope if scope
|
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]
|
if options[:source_type]
|
||||||
through_scope_chain.first <<
|
through_scope_chain.first <<
|
||||||
|
@ -18,6 +18,11 @@
|
|||||||
require 'models/tag'
|
require 'models/tag'
|
||||||
require 'models/sponsor'
|
require 'models/sponsor'
|
||||||
require 'models/edge'
|
require 'models/edge'
|
||||||
|
require 'models/hotel'
|
||||||
|
require 'models/chef'
|
||||||
|
require 'models/department'
|
||||||
|
require 'models/cake_designer'
|
||||||
|
require 'models/drink_designer'
|
||||||
|
|
||||||
class ReflectionTest < ActiveRecord::TestCase
|
class ReflectionTest < ActiveRecord::TestCase
|
||||||
include ActiveRecord::Reflection
|
include ActiveRecord::Reflection
|
||||||
@ -227,6 +232,17 @@ def test_scope_chain
|
|||||||
assert_equal expected, actual
|
assert_equal expected, actual
|
||||||
end
|
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?
|
def test_nested?
|
||||||
assert !Author.reflect_on_association(:comments).nested?
|
assert !Author.reflect_on_association(:comments).nested?
|
||||||
assert Author.reflect_on_association(:tags).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 @@ def create_table(*args, &block)
|
|||||||
t.string 'from'
|
t.string 'from'
|
||||||
end
|
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
|
except 'SQLite' do
|
||||||
# fk_test_has_fk should be before fk_test_has_pk
|
# fk_test_has_fk should be before fk_test_has_pk
|
||||||
create_table :fk_test_has_fk, :force => true do |t|
|
create_table :fk_test_has_fk, :force => true do |t|
|
||||||
|
Loading…
Reference in New Issue
Block a user