diff options
author | Ryuta Kamizono <kamipo@gmail.com> | 2017-01-09 01:43:08 +0900 |
---|---|---|
committer | Ryuta Kamizono <kamipo@gmail.com> | 2017-08-13 16:17:35 +0900 |
commit | b23e86967c4dfa5aa4f007291458c48dd39b179a (patch) | |
tree | bf35c7a8d0fc2eb722e67a9fb1291d81861f614c /activerecord/lib/active_record | |
parent | e3962308e7947f3d99c70c192e2d1356d3420e1e (diff) | |
download | rails-b23e86967c4dfa5aa4f007291458c48dd39b179a.tar.gz rails-b23e86967c4dfa5aa4f007291458c48dd39b179a.tar.bz2 rails-b23e86967c4dfa5aa4f007291458c48dd39b179a.zip |
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.
Diffstat (limited to 'activerecord/lib/active_record')
-rw-r--r-- | activerecord/lib/active_record/associations/collection_association.rb | 11 | ||||
-rw-r--r-- | activerecord/lib/active_record/reflection.rb | 4 |
2 files changed, 11 insertions, 4 deletions
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: |