From a4eb8d4ab4ae48c8d8de75ec0c1038bc91549922 Mon Sep 17 00:00:00 2001 From: Maxim Chernyak Date: Mon, 31 May 2010 21:18:28 -0400 Subject: [PATCH] Fix eager loading of polymorphic has_one associations nested-included under polymorphic belongs_to associations. [#3233 state:resolved] --- .../lib/active_record/association_preload.rb | 8 +++++++- .../eager_load_nested_polymorphic_include.rb | 19 +++++++++++++++++++ activerecord/test/fixtures/polymorphic_designs.yml | 19 +++++++++++++++++++ activerecord/test/fixtures/polymorphic_prices.yml | 19 +++++++++++++++++++ activerecord/test/fixtures/tees.yml | 4 ++++ activerecord/test/fixtures/ties.yml | 4 ++++ activerecord/test/models/polymorphic_design.rb | 3 +++ activerecord/test/models/polymorphic_price.rb | 3 +++ activerecord/test/models/tee.rb | 4 ++++ activerecord/test/models/tie.rb | 4 ++++ activerecord/test/schema/schema.rb | 14 ++++++++++++++ 11 files changed, 100 insertions(+), 1 deletions(-) create mode 100644 activerecord/test/cases/associations/eager_load_nested_polymorphic_include.rb create mode 100644 activerecord/test/fixtures/polymorphic_designs.yml create mode 100644 activerecord/test/fixtures/polymorphic_prices.yml create mode 100644 activerecord/test/fixtures/tees.yml create mode 100644 activerecord/test/fixtures/ties.yml create mode 100644 activerecord/test/models/polymorphic_design.rb create mode 100644 activerecord/test/models/polymorphic_price.rb create mode 100644 activerecord/test/models/tee.rb create mode 100644 activerecord/test/models/tie.rb diff --git a/activerecord/lib/active_record/association_preload.rb b/activerecord/lib/active_record/association_preload.rb index 2310649..487a2bb 100644 --- a/activerecord/lib/active_record/association_preload.rb +++ b/activerecord/lib/active_record/association_preload.rb @@ -357,7 +357,13 @@ module ActiveRecord table_name = reflection.klass.quoted_table_name if interface = reflection.options[:as] - conditions = "#{reflection.klass.quoted_table_name}.#{connection.quote_column_name "#{interface}_id"} #{in_or_equals_for_ids(ids)} and #{reflection.klass.quoted_table_name}.#{connection.quote_column_name "#{interface}_type"} = '#{self.base_class.sti_name}'" + parent_type = if reflection.active_record.abstract_class? + self.base_class.sti_name + else + reflection.active_record.sti_name + end + + conditions = "#{reflection.klass.quoted_table_name}.#{connection.quote_column_name "#{interface}_id"} #{in_or_equals_for_ids(ids)} and #{reflection.klass.quoted_table_name}.#{connection.quote_column_name "#{interface}_type"} = '#{parent_type}'" else foreign_key = reflection.primary_key_name conditions = "#{reflection.klass.quoted_table_name}.#{foreign_key} #{in_or_equals_for_ids(ids)}" diff --git a/activerecord/test/cases/associations/eager_load_nested_polymorphic_include.rb b/activerecord/test/cases/associations/eager_load_nested_polymorphic_include.rb new file mode 100644 index 0000000..3b8efe9 --- /dev/null +++ b/activerecord/test/cases/associations/eager_load_nested_polymorphic_include.rb @@ -0,0 +1,19 @@ +require 'cases/helper' +require 'models/tee' +require 'models/tie' +require 'models/polymorphic_design' +require 'models/polymorphic_price' + +class EagerLoadNestedPolymorphicIncludeTest < ActiveRecord::TestCase + fixtures :tees, :ties, :polymorphic_designs, :polymorphic_prices + + def test_eager_load_polymorphic_has_one_nested_under_polymorphic_belongs_to + designs = PolymorphicDesign.scoped(:include => {:designable => :polymorphic_price}) + + associated_price_ids = designs.map{|design| design.designable.polymorphic_price.id} + expected_price_ids = [1, 2, 3, 4] + + assert expected_price_ids.all?{|expected_id| associated_price_ids.include?(expected_id)}, + "Expected associated prices to be #{expected_price_ids.inspect} but they were #{associated_price_ids.sort.inspect}" + end +end diff --git a/activerecord/test/fixtures/polymorphic_designs.yml b/activerecord/test/fixtures/polymorphic_designs.yml new file mode 100644 index 0000000..ebc481f --- /dev/null +++ b/activerecord/test/fixtures/polymorphic_designs.yml @@ -0,0 +1,19 @@ +awesome_tee_design: + id: 1 + designable_id: 1 + designable_type: Tee + +sucky_tee_design: + id: 2 + designable_id: 2 + designable_type: Tee + +awesome_hat_design: + id: 3 + designable_id: 1 + designable_type: Tie + +sucky_hat_design: + id: 4 + designable_id: 2 + designable_type: Tie \ No newline at end of file diff --git a/activerecord/test/fixtures/polymorphic_prices.yml b/activerecord/test/fixtures/polymorphic_prices.yml new file mode 100644 index 0000000..3aca5fa --- /dev/null +++ b/activerecord/test/fixtures/polymorphic_prices.yml @@ -0,0 +1,19 @@ +awesome_tee_price: + id: 1 + sellable_id: 1 + sellable_type: Tee + +sucky_tee_price: + id: 2 + sellable_id: 2 + sellable_type: Tee + +awesome_hat_price: + id: 3 + sellable_id: 1 + sellable_type: Tie + +sucky_hat_price: + id: 4 + sellable_id: 2 + sellable_type: Tie \ No newline at end of file diff --git a/activerecord/test/fixtures/tees.yml b/activerecord/test/fixtures/tees.yml new file mode 100644 index 0000000..d6df60f --- /dev/null +++ b/activerecord/test/fixtures/tees.yml @@ -0,0 +1,4 @@ +awesome_tee: + id: 1 +sucky_tee: + id: 2 \ No newline at end of file diff --git a/activerecord/test/fixtures/ties.yml b/activerecord/test/fixtures/ties.yml new file mode 100644 index 0000000..f930809 --- /dev/null +++ b/activerecord/test/fixtures/ties.yml @@ -0,0 +1,4 @@ +awesome_tie: + id: 1 +sucky_tie: + id: 2 \ No newline at end of file diff --git a/activerecord/test/models/polymorphic_design.rb b/activerecord/test/models/polymorphic_design.rb new file mode 100644 index 0000000..6748f8f --- /dev/null +++ b/activerecord/test/models/polymorphic_design.rb @@ -0,0 +1,3 @@ +class PolymorphicDesign < ActiveRecord::Base + belongs_to :designable, :polymorphic => true +end \ No newline at end of file diff --git a/activerecord/test/models/polymorphic_price.rb b/activerecord/test/models/polymorphic_price.rb new file mode 100644 index 0000000..bea8566 --- /dev/null +++ b/activerecord/test/models/polymorphic_price.rb @@ -0,0 +1,3 @@ +class PolymorphicPrice < ActiveRecord::Base + belongs_to :sellable, :polymorphic => true +end \ No newline at end of file diff --git a/activerecord/test/models/tee.rb b/activerecord/test/models/tee.rb new file mode 100644 index 0000000..63311a7 --- /dev/null +++ b/activerecord/test/models/tee.rb @@ -0,0 +1,4 @@ +class Tee < ActiveRecord::Base + has_one :polymorphic_design, :as => :designable + has_one :polymorphic_price, :as => :sellable +end \ No newline at end of file diff --git a/activerecord/test/models/tie.rb b/activerecord/test/models/tie.rb new file mode 100644 index 0000000..cdf1740 --- /dev/null +++ b/activerecord/test/models/tie.rb @@ -0,0 +1,4 @@ +class Tie < ActiveRecord::Base + has_one :polymorphic_design, :as => :designable + has_one :polymorphic_price, :as => :sellable +end \ No newline at end of file diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb index c8e652a..804805c 100644 --- a/activerecord/test/schema/schema.rb +++ b/activerecord/test/schema/schema.rb @@ -367,6 +367,16 @@ ActiveRecord::Schema.define do t.column :updated_on, :datetime end + create_table :polymorphic_designs, :force => true do |t| + t.integer :designable_id + t.string :designable_type + end + + create_table :polymorphic_prices, :force => true do |t| + t.integer :sellable_id + t.string :sellable_type + end + create_table :posts, :force => true do |t| t.integer :author_id t.string :title, :null => false @@ -435,6 +445,8 @@ ActiveRecord::Schema.define do t.datetime :ending end + create_table :ties, :force => true + create_table :topics, :force => true do |t| t.string :title t.string :author_name @@ -462,6 +474,8 @@ ActiveRecord::Schema.define do t.column :taggings_count, :integer, :default => 0 end + create_table :tees, :force => true + create_table :toys, :primary_key => :toy_id ,:force => true do |t| t.string :name t.integer :pet_id, :integer -- 1.6.4.2