Merge pull request #10538 from neerajdotname/3882

scope_chain should not be mutated for other reflections
This commit is contained in:
Rafael Mendonça França 2013-10-14 12:26:10 -07:00
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 @@ def scope_chain
# 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/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 @@ def test_scope_chain
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?

@ -0,0 +1,3 @@
class CakeDesigner < ActiveRecord::Base
has_one :chef, as: :employable
end

@ -0,0 +1,3 @@
class Chef < ActiveRecord::Base
belongs_to :employable, polymorphic: true
end

@ -0,0 +1,4 @@
class Department < ActiveRecord::Base
has_many :chefs
belongs_to :hotel
end

@ -0,0 +1,3 @@
class DrinkDesigner < ActiveRecord::Base
has_one :chef, as: :employable
end

@ -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'
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|