aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
authorAaron Patterson <aaron.patterson@gmail.com>2014-03-31 10:11:33 -0700
committerAaron Patterson <aaron.patterson@gmail.com>2014-03-31 10:11:33 -0700
commitb88cfed7ab0993f46cf71eebf69c23191da6f9d4 (patch)
tree90bce80ab373b6cff0108807198f634761804a07 /activerecord
parent5eb13fcaac5c7328e048bf4e5d2d8418fefc5ac1 (diff)
parent055942d6c526de3a037e76e14954229888668515 (diff)
downloadrails-b88cfed7ab0993f46cf71eebf69c23191da6f9d4.tar.gz
rails-b88cfed7ab0993f46cf71eebf69c23191da6f9d4.tar.bz2
rails-b88cfed7ab0993f46cf71eebf69c23191da6f9d4.zip
Merge pull request #14532 from thedarkone/polymorphic-preload-fix
Fix polymorphic preloads on NOT NULL _type columns
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/lib/active_record/associations.rb8
-rw-r--r--activerecord/lib/active_record/associations/preloader.rb35
-rw-r--r--activerecord/test/cases/associations/eager_test.rb19
3 files changed, 28 insertions, 34 deletions
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index 860e76fa18..4abe2ad0a0 100644
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -4,6 +4,12 @@ require 'active_support/core_ext/module/remove_method'
require 'active_record/errors'
module ActiveRecord
+ class AssociationNotFoundError < ConfigurationError #:nodoc:
+ def initialize(record, association_name)
+ super("Association named '#{association_name}' was not found on #{record.class.name}; perhaps you misspelled it?")
+ end
+ end
+
class InverseOfAssociationNotFoundError < ActiveRecordError #:nodoc:
def initialize(reflection, associated_class = nil)
super("Could not find the inverse association for #{reflection.name} (#{reflection.options[:inverse_of].inspect} in #{associated_class.nil? ? reflection.class_name : associated_class.name})")
@@ -145,7 +151,7 @@ module ActiveRecord
association = association_instance_get(name)
if association.nil?
- reflection = self.class.reflect_on_association(name)
+ raise AssociationNotFoundError.new(self, name) unless reflection = self.class.reflect_on_association(name)
association = reflection.association_class.new(self, reflection)
association_instance_set(name, association)
end
diff --git a/activerecord/lib/active_record/associations/preloader.rb b/activerecord/lib/active_record/associations/preloader.rb
index 83637a0409..31ddf4e0fc 100644
--- a/activerecord/lib/active_record/associations/preloader.rb
+++ b/activerecord/lib/active_record/associations/preloader.rb
@@ -140,36 +140,13 @@ module ActiveRecord
end
def grouped_records(association, records)
- reflection_records = records_by_reflection(association, records)
-
- reflection_records.each_with_object({}) do |(reflection, r_records),h|
- h[reflection] = r_records.group_by { |record|
- association_klass(reflection, record)
- }
- end
- end
-
- def records_by_reflection(association, records)
- records.group_by do |record|
- reflection = record.class.reflect_on_association(association)
-
- reflection || raise_config_error(record, association)
- end
- end
-
- def raise_config_error(record, association)
- raise ActiveRecord::ConfigurationError,
- "Association named '#{association}' was not found on #{record.class.name}; " \
- "perhaps you misspelled it?"
- end
-
- def association_klass(reflection, record)
- if reflection.macro == :belongs_to && reflection.options[:polymorphic]
- klass = record.read_attribute(reflection.foreign_type.to_s)
- klass && klass.constantize
- else
- reflection.klass
+ h = {}
+ records.each do |record|
+ assoc = record.association(association)
+ klasses = h[assoc.reflection] ||= {}
+ (klasses[assoc.klass] ||= []) << record
end
+ h
end
class AlreadyLoaded
diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb
index e59161fc5b..8c9797861c 100644
--- a/activerecord/test/cases/associations/eager_test.rb
+++ b/activerecord/test/cases/associations/eager_test.rb
@@ -235,6 +235,17 @@ class EagerAssociationTest < ActiveRecord::TestCase
end
end
+ def test_finding_with_includes_on_empty_polymorphic_type_column
+ sponsor = sponsors(:moustache_club_sponsor_for_groucho)
+ sponsor.update!(sponsorable_type: '', sponsorable_id: nil) # sponsorable_type column might be declared NOT NULL
+ sponsor = assert_queries(1) do
+ assert_nothing_raised { Sponsor.all.merge!(:includes => :sponsorable).find(sponsor.id) }
+ end
+ assert_no_queries do
+ assert_equal nil, sponsor.sponsorable
+ end
+ end
+
def test_loading_from_an_association
posts = authors(:david).posts.merge(:includes => :comments, :order => "posts.id").to_a
assert_equal 2, posts.first.comments.size
@@ -709,16 +720,16 @@ class EagerAssociationTest < ActiveRecord::TestCase
end
def test_eager_with_invalid_association_reference
- assert_raise(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") {
+ assert_raise(ActiveRecord::AssociationNotFoundError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") {
Post.all.merge!(:includes=> :monkeys ).find(6)
}
- assert_raise(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") {
+ assert_raise(ActiveRecord::AssociationNotFoundError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") {
Post.all.merge!(:includes=>[ :monkeys ]).find(6)
}
- assert_raise(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") {
+ assert_raise(ActiveRecord::AssociationNotFoundError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") {
Post.all.merge!(:includes=>[ 'monkeys' ]).find(6)
}
- assert_raise(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys, :elephants") {
+ assert_raise(ActiveRecord::AssociationNotFoundError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys, :elephants") {
Post.all.merge!(:includes=>[ :monkeys, :elephants ]).find(6)
}
end