aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/lib/active_record/association_preload.rb6
-rw-r--r--activerecord/test/cases/associations/eager_load_nested_include_test.rb114
2 files changed, 119 insertions, 1 deletions
diff --git a/activerecord/lib/active_record/association_preload.rb b/activerecord/lib/active_record/association_preload.rb
index 9ef8ed15e8..313c51dae0 100644
--- a/activerecord/lib/active_record/association_preload.rb
+++ b/activerecord/lib/active_record/association_preload.rb
@@ -34,7 +34,11 @@ module ActiveRecord
reflection = reflections[association]
raise ConfigurationError, "Association named '#{ association }' was not found; perhaps you misspelled it?" unless reflection
- send(:"preload_#{reflection.macro}_association", records, reflection, preload_options)
+ # Not all records have the same class, so group then preload.
+ records.group_by(&:class).each do |klass, records|
+ reflection = klass.reflections[association]
+ send("preload_#{reflection.macro}_association", records, reflection, preload_options)
+ end
end
def add_preloaded_records_to_collection(parent_records, reflection_name, associated_record)
diff --git a/activerecord/test/cases/associations/eager_load_nested_include_test.rb b/activerecord/test/cases/associations/eager_load_nested_include_test.rb
new file mode 100644
index 0000000000..106f0691b6
--- /dev/null
+++ b/activerecord/test/cases/associations/eager_load_nested_include_test.rb
@@ -0,0 +1,114 @@
+require 'cases/helper'
+
+class EagerLoadPolyAssocsTest < Test::Unit::TestCase
+ NUM_SIMPLE_OBJS = 50
+ NUM_SHAPE_EXPRESSIONS = 100
+
+ def setup
+ silence_stream(STDOUT) { create_test_tables }
+ generate_test_object_graphs
+ end
+
+ def create_test_tables
+ conn = ActiveRecord::Base.connection
+ options = { :force => true, :options => "Engine=MyISAM" }
+
+ [:circles, :squares, :triangles, :non_poly_ones, :non_poly_twos].each do |t|
+ conn.create_table(t, options) { }
+ end
+
+ conn.create_table :shape_expressions, options do |t|
+ t.string :paint_type
+ t.integer :paint_id
+ t.string :shape_type
+ t.integer :shape_id
+ end
+ conn.create_table :paint_colors, options do |t|
+ t.integer :non_poly_one_id
+ end
+ conn.create_table :paint_textures, options do |t|
+ t.integer :non_poly_two_id
+ end
+ end
+
+ def teardown
+ drop_tables
+ end
+
+ def drop_tables
+ conn = ActiveRecord::Base.connection
+ conn.reconnect!
+
+ silence_stream(STDOUT) do
+ [:circles, :squares, :triangles, :paint_colors, :paint_textures,
+ :shape_expressions, :non_poly_ones, :non_poly_twos].each do |t|
+ conn.drop_table t
+ end
+ end
+ end
+
+ # meant to be supplied as an ID, never returns 0
+ def rand_simple
+ val = (NUM_SIMPLE_OBJS * rand).round
+ val == 0 ? 1 : val
+ end
+
+ def generate_test_object_graphs
+ 1.upto(NUM_SIMPLE_OBJS) do
+ [Circle, Square, Triangle, NonPolyOne, NonPolyTwo].map(&:create!)
+ end
+ 1.upto(NUM_SIMPLE_OBJS) do |i|
+ PaintColor.create!(:non_poly_one_id => rand_simple)
+ PaintTexture.create!(:non_poly_two_id => rand_simple)
+ end
+ 1.upto(NUM_SHAPE_EXPRESSIONS) do |i|
+ ShapeExpression.create!(:shape_type => [Circle, Square, Triangle].rand.to_s, :shape_id => rand_simple,
+ :paint_type => [PaintColor, PaintTexture].rand.to_s, :paint_id => rand_simple)
+ end
+ end
+
+ def test_include_query
+ res = 0
+ res = ShapeExpression.find :all, :include => [ :shape, { :paint => :non_poly } ]
+ assert_equal NUM_SHAPE_EXPRESSIONS, res.size
+ ShapeExpression.connection.disconnect!
+ assert_nothing_raised "confirm we can access associations in memory" do
+ res.each do |se|
+ assert_not_nil se.paint.non_poly, "this is the association that was loading incorrectly before the change"
+ assert_not_nil se.shape, "just making sure other associations still work"
+ end
+ end
+ assert_raise ActiveRecord::StatementInvalid, "An exception should be raised when db connectivity is required" do
+ res[0].reload
+ end
+ end
+end
+
+class ShapeExpression < ActiveRecord::Base
+ belongs_to :shape, :polymorphic => true
+ belongs_to :paint, :polymorphic => true
+end
+
+class Circle < ActiveRecord::Base
+ has_many :shape_expressions, :as => :shape
+end
+class Square < ActiveRecord::Base
+ has_many :shape_expressions, :as => :shape
+end
+class Triangle < ActiveRecord::Base
+ has_many :shape_expressions, :as => :shape
+end
+class PaintColor < ActiveRecord::Base
+ has_many :shape_expressions, :as => :paint
+ belongs_to :non_poly, :foreign_key => "non_poly_one_id", :class_name => "NonPolyOne"
+end
+class PaintTexture < ActiveRecord::Base
+ has_many :shape_expressions, :as => :paint
+ belongs_to :non_poly, :foreign_key => "non_poly_two_id", :class_name => "NonPolyTwo"
+end
+class NonPolyOne < ActiveRecord::Base
+ has_many :paint_colors
+end
+class NonPolyTwo < ActiveRecord::Base
+ has_many :paint_textures
+end