From b23e86967c4dfa5aa4f007291458c48dd39b179a Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Mon, 9 Jan 2017 01:43:08 +0900 Subject: Fix `reflection.association_primary_key` for `has_many` associations It is incorrect to treat `options[:primary_key]` as `association_primary_key` if `has_many` associations because the `:primary_key` means the column on the owner record, not on the association record. It will break `ids_reader` and `ids_writer`. ```ruby people(:david).essay_ids # => ActiveRecord::StatementInvalid: Mysql2::Error: Unknown column 'essays.first_name' in 'field list': SELECT `essays`.first_name FROM `essays` WHERE `essays`.`writer_id` = 'David' ``` Fixes #14439. --- .../lib/active_record/associations/collection_association.rb | 11 +++++++---- activerecord/lib/active_record/reflection.rb | 4 ++++ 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb index 1a424896fe..ea9ab297d1 100644 --- a/activerecord/lib/active_record/associations/collection_association.rb +++ b/activerecord/lib/active_record/associations/collection_association.rb @@ -55,13 +55,16 @@ module ActiveRecord pk_type = reflection.association_primary_key_type ids = Array(ids).reject(&:blank?) ids.map! { |i| pk_type.cast(i) } - records = klass.where(reflection.association_primary_key => ids).index_by do |r| - r.send(reflection.association_primary_key) + + primary_key = reflection.association_primary_key + records = klass.where(primary_key => ids).index_by do |r| + r.public_send(primary_key) end.values_at(*ids).compact + if records.size != ids.size - found_ids = records.map { |record| record.send(reflection.association_primary_key) } + found_ids = records.map { |record| record.public_send(primary_key) } not_found_ids = ids - found_ids - klass.all.raise_record_not_found_exception!(ids, records.size, ids.size, reflection.association_primary_key, not_found_ids) + klass.all.raise_record_not_found_exception!(ids, records.size, ids.size, primary_key, not_found_ids) else replace(records) end diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index d2b85e168b..8e1ef840fa 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -715,6 +715,10 @@ module ActiveRecord Associations::HasManyAssociation end end + + def association_primary_key(klass = nil) + primary_key(klass || self.klass) + end end class HasOneReflection < AssociationReflection # :nodoc: -- cgit v1.2.3