aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--activerecord/lib/active_record/association_preload.rb25
-rw-r--r--activerecord/lib/active_record/associations/has_one_association.rb3
-rw-r--r--activerecord/test/cases/finder_test.rb2
-rw-r--r--activerecord/test/fixtures/companies.yml1
4 files changed, 21 insertions, 10 deletions
diff --git a/activerecord/lib/active_record/association_preload.rb b/activerecord/lib/active_record/association_preload.rb
index 83383e9b19..7b4ff69b87 100644
--- a/activerecord/lib/active_record/association_preload.rb
+++ b/activerecord/lib/active_record/association_preload.rb
@@ -379,18 +379,20 @@ module ActiveRecord
end
def find_associated_records(ids, reflection, preload_options)
- options = reflection.options
+ options = reflection.options
+ table = reflection.klass.arel_table
table_name = reflection.klass.quoted_table_name
+ conditions = []
+
+ key = reflection.primary_key_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}'"
- else
- foreign_key = reflection.primary_key_name
- conditions = "#{reflection.klass.quoted_table_name}.#{foreign_key} #{in_or_equals_for_ids(ids)}"
+ key = "#{interface}_id"
+ conditions << table["#{interface}_type"].eq(base_class.sti_name)
end
- conditions = ([conditions] +
- append_conditions(reflection, preload_options)).join(' AND ')
+ conditions += append_conditions(reflection, preload_options)
find_options = {
:select => preload_options[:select] || options[:select] || Arel.sql("#{table_name}.*"),
@@ -401,7 +403,14 @@ module ActiveRecord
}
associated_records(ids) do |some_ids|
- reflection.klass.scoped.apply_finder_options(find_options.merge(:conditions => [conditions, some_ids])).to_a
+ method = some_ids.length == 1 ? ['eq', some_ids.first] :
+ ['in', some_ids]
+
+ where = conditions.inject(table[key].send(*method)) do |ast, cond|
+ ast.and cond
+ end
+
+ reflection.klass.scoped.apply_finder_options(find_options.merge(:conditions => where)).to_a
end
end
diff --git a/activerecord/lib/active_record/associations/has_one_association.rb b/activerecord/lib/active_record/associations/has_one_association.rb
index c49fd6e66a..d08cbea199 100644
--- a/activerecord/lib/active_record/associations/has_one_association.rb
+++ b/activerecord/lib/active_record/associations/has_one_association.rb
@@ -89,7 +89,8 @@ module ActiveRecord
"#{@reflection.quoted_table_name}.#{@reflection.options[:as]}_id = #{owner_quoted_id} AND " +
"#{@reflection.quoted_table_name}.#{@reflection.options[:as]}_type = #{@owner.class.quote_value(@owner.class.base_class.name.to_s)}"
else
- sql = "#{@reflection.quoted_table_name}.#{@reflection.primary_key_name} = #{owner_quoted_id}"
+ test = owner_quoted_id == "NULL" ? "IS" : "="
+ sql = "#{@reflection.quoted_table_name}.#{@reflection.primary_key_name} #{test} #{owner_quoted_id}"
end
sql << " AND (#{conditions})" if conditions
{ :conditions => sql }
diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb
index 31e4981a1d..c35590b84b 100644
--- a/activerecord/test/cases/finder_test.rb
+++ b/activerecord/test/cases/finder_test.rb
@@ -982,7 +982,7 @@ class FinderTest < ActiveRecord::TestCase
def test_select_rows
assert_equal(
- [["1", nil, nil, "37signals"],
+ [["1", "1", nil, "37signals"],
["2", "1", "2", "Summit"],
["3", "1", "1", "Microsoft"]],
Company.connection.select_rows("SELECT id, firm_id, client_of, name FROM companies WHERE id IN (1,2,3) ORDER BY id").map! {|i| i.map! {|j| j.to_s unless j.nil?}})
diff --git a/activerecord/test/fixtures/companies.yml b/activerecord/test/fixtures/companies.yml
index ffaa097686..30b73d8e84 100644
--- a/activerecord/test/fixtures/companies.yml
+++ b/activerecord/test/fixtures/companies.yml
@@ -9,6 +9,7 @@ first_client:
first_firm:
id: 1
+ firm_id: 1
type: Firm
name: 37signals
ruby_type: Firm