diff --git a/actionpack/lib/action_controller/url_encoded_pair_parser.rb b/actionpack/lib/action_controller/url_encoded_pair_parser.rb index bea96c711daad..9883ad0d85115 100644 --- a/actionpack/lib/action_controller/url_encoded_pair_parser.rb +++ b/actionpack/lib/action_controller/url_encoded_pair_parser.rb @@ -70,11 +70,12 @@ def bind(key, value) top[-1][key] = value else top << {key => value}.with_indifferent_access - push top.last - value = top[key] end + push top.last + return top[key] else top << value + return value end elsif top.is_a? Hash key = CGI.unescape(key) @@ -84,12 +85,10 @@ def bind(key, value) else raise ArgumentError, "Don't know what to do: top is #{top.inspect}" end - - return value end def type_conflict!(klass, value) raise TypeError, "Conflicting types for parameter containers. Expected an instance of #{klass} but found an instance of #{value.class}. This can be caused by colliding Array and Hash parameters like qs[]=value&qs[key]=value. (The parameters received were #{value.inspect}.)" end end -end \ No newline at end of file +end diff --git a/actionpack/test/controller/request_test.rb b/actionpack/test/controller/request_test.rb index 349cea268f845..c93d3152b80fa 100644 --- a/actionpack/test/controller/request_test.rb +++ b/actionpack/test/controller/request_test.rb @@ -441,6 +441,7 @@ def test_deep_query_string_with_array def test_deep_query_string_with_array_of_hash assert_equal({'x' => {'y' => [{'z' => '10'}]}}, ActionController::RequestParser.parse_query_parameters('x[y][][z]=10')) assert_equal({'x' => {'y' => [{'z' => '10', 'w' => '10'}]}}, ActionController::RequestParser.parse_query_parameters('x[y][][z]=10&x[y][][w]=10')) + assert_equal({'x' => {'y' => [{'z' => '10', 'v' => {'w' => '10'}}]}}, ActionController::RequestParser.parse_query_parameters('x[y][][z]=10&x[y][][v][w]=10')) end def test_deep_query_string_with_array_of_hashes_with_one_pair diff --git a/activerecord/lib/active_record/association_preload.rb b/activerecord/lib/active_record/association_preload.rb index 9d0bf3a308dd9..e4ab69aa1b767 100644 --- a/activerecord/lib/active_record/association_preload.rb +++ b/activerecord/lib/active_record/association_preload.rb @@ -195,7 +195,7 @@ def preload_has_and_belongs_to_many_association(records, reflection, preload_opt def preload_has_one_association(records, reflection, preload_options={}) return if records.first.send("loaded_#{reflection.name}?") - id_to_record_map, ids = construct_id_map(records) + id_to_record_map, ids = construct_id_map(records, reflection.options[:primary_key]) options = reflection.options records.each {|record| record.send("set_#{reflection.name}_target", nil)} if options[:through] @@ -229,7 +229,7 @@ def preload_has_many_association(records, reflection, preload_options={}) options = reflection.options primary_key_name = reflection.through_reflection_primary_key_name - id_to_record_map, ids = construct_id_map(records, primary_key_name) + id_to_record_map, ids = construct_id_map(records, primary_key_name || reflection.options[:primary_key]) records.each {|record| record.send(reflection.name).loaded} if options[:through] diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index c154a5087cdb3..86616abf52fc8 100755 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -22,7 +22,7 @@ def initialize(reflection) through_reflection = reflection.through_reflection source_reflection_names = reflection.source_reflection_names source_associations = reflection.through_reflection.klass.reflect_on_all_associations.collect { |a| a.name.inspect } - super("Could not find the source association(s) #{source_reflection_names.collect(&:inspect).to_sentence :connector => 'or'} in model #{through_reflection.klass}. Try 'has_many #{reflection.name.inspect}, :through => #{through_reflection.name.inspect}, :source => '. Is it one of #{source_associations.to_sentence :connector => 'or'}?") + super("Could not find the source association(s) #{source_reflection_names.collect(&:inspect).to_sentence :two_words_connector => ' or ', :last_word_connector => ', or '} in model #{through_reflection.klass}. Try 'has_many #{reflection.name.inspect}, :through => #{through_reflection.name.inspect}, :source => '. Is it one of #{source_associations.to_sentence :two_words_connector => ' or ', :last_word_connector => ', or '}?") end end @@ -2171,7 +2171,7 @@ def association_join aliased_table_name, foreign_key, parent.aliased_table_name, - parent.primary_key + reflection.options[:primary_key] || parent.primary_key ] end when :belongs_to diff --git a/activerecord/lib/active_record/associations/association_proxy.rb b/activerecord/lib/active_record/associations/association_proxy.rb index 59f1d3b867997..676c4ace61df2 100644 --- a/activerecord/lib/active_record/associations/association_proxy.rb +++ b/activerecord/lib/active_record/associations/association_proxy.rb @@ -180,7 +180,10 @@ def set_belongs_to_association_for(record) record["#{@reflection.options[:as]}_id"] = @owner.id unless @owner.new_record? record["#{@reflection.options[:as]}_type"] = @owner.class.base_class.name.to_s else - record[@reflection.primary_key_name] = @owner.id unless @owner.new_record? + unless @owner.new_record? + primary_key = @reflection.options[:primary_key] || :id + record[@reflection.primary_key_name] = @owner.send(primary_key) + end end end diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb index afbd9fddf9559..14099d417673a 100644 --- a/activerecord/test/cases/associations/eager_test.rb +++ b/activerecord/test/cases/associations/eager_test.rb @@ -786,4 +786,37 @@ def test_preload_has_many_uses_exclusive_scope assert_equal Person.find(person.id).agents, person.agents end end + + def test_preload_has_many_using_primary_key + expected = Firm.find(:first).clients_using_primary_key.to_a + firm = Firm.find :first, :include => :clients_using_primary_key + assert_no_queries do + assert_equal expected, firm.clients_using_primary_key + end + end + + def test_include_has_many_using_primary_key + expected = Firm.find(1).clients_using_primary_key.sort_by &:name + firm = Firm.find 1, :include => :clients_using_primary_key, :order => 'clients_using_primary_keys_companies.name' + assert_no_queries do + assert_equal expected, firm.clients_using_primary_key + end + end + + def test_preload_has_one_using_primary_key + expected = Firm.find(:first).account_using_primary_key + firm = Firm.find :first, :include => :account_using_primary_key + assert_no_queries do + assert_equal expected, firm.account_using_primary_key + end + end + + def test_include_has_one_using_primary_key + expected = Firm.find(1).account_using_primary_key + firm = Firm.find(:all, :include => :account_using_primary_key, :order => 'accounts.id').detect {|f| f.id == 1} + assert_no_queries do + assert_equal expected, firm.account_using_primary_key + end + end + end diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index 20b9acda4461b..a5ae5cd8ec779 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -1115,5 +1115,11 @@ def test_respond_to_private_class_methods assert !client_association.respond_to?(:private_method) assert client_association.respond_to?(:private_method, true) end + + def test_creating_using_primary_key + firm = Firm.find(:first) + client = firm.clients_using_primary_key.create!(:name => 'test') + assert_equal firm.name, client.firm_name + end end