Skip to content

Commit 9355020

Browse files
committed
Add test for collection *_ids= setter when association primary key set
Fixes casting of IDs to the data type of the association primary key, rather than then the data type of the model's primary key. (Tests use a string primary key on the association, rather than an int.) Tests issue rails#20995
1 parent 15e2da6 commit 9355020

File tree

4 files changed

+23
-1
lines changed

4 files changed

+23
-1
lines changed

activerecord/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
* Raise ActiveRecord::RecordNotFound from collection `*_ids` setters
22
for unknown IDs with a better error message.
33

4+
Changes the collection `*_ids` setters to cast provided IDs the data
5+
type of the primary key set in the association, not the model
6+
primary key.
7+
48
*Dominic Cleal*
59

610
* For PostgreSQL >= 9.4 use `pgcrypto`'s `gen_random_uuid()` instead of

activerecord/lib/active_record/associations/collection_association.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ def ids_reader
6868

6969
# Implements the ids writer method, e.g. foo.item_ids= for Foo.has_many :items
7070
def ids_writer(ids)
71-
pk_type = reflection.primary_key_type
71+
pk_type = reflection.association_primary_key_type
7272
ids = Array(ids).reject(&:blank?)
7373
ids.map! { |i| pk_type.cast(i) }
7474
records = klass.where(reflection.association_primary_key => ids).index_by do |r|

activerecord/lib/active_record/reflection.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,10 @@ def association_primary_key(klass = nil)
397397
options[:primary_key] || primary_key(klass || self.klass)
398398
end
399399

400+
def association_primary_key_type
401+
klass.type_for_attribute(association_primary_key)
402+
end
403+
400404
def active_record_primary_key
401405
@active_record_primary_key ||= options[:primary_key] || primary_key(active_record)
402406
end

activerecord/test/cases/associations/has_many_through_associations_test.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -883,13 +883,27 @@ def test_collection_singular_ids_setter_with_string_primary_keys
883883

884884
end
885885

886+
def test_collection_singular_ids_setter_with_changed_primary_key
887+
company = companies(:first_firm)
888+
client = companies(:first_client)
889+
company.clients_using_primary_key_ids = [client.name]
890+
assert_equal [client], company.clients_using_primary_key
891+
end
892+
886893
def test_collection_singular_ids_setter_raises_exception_when_invalid_ids_set
887894
company = companies(:rails_core)
888895
ids = [Developer.first.id, -9999]
889896
e = assert_raises(ActiveRecord::RecordNotFound) { company.developer_ids = ids }
890897
assert_match(/Couldn't find all Developers with 'id'/, e.message)
891898
end
892899

900+
def test_collection_singular_ids_setter_raises_exception_when_invalid_ids_set_with_changed_primary_key
901+
company = companies(:first_firm)
902+
ids = [Client.first.name, "unknown client"]
903+
e = assert_raises(ActiveRecord::RecordNotFound) { company.clients_using_primary_key_ids = ids }
904+
assert_match(/Couldn't find all Clients with 'name'/, e.message)
905+
end
906+
893907
def test_build_a_model_from_hm_through_association_with_where_clause
894908
assert_nothing_raised { books(:awdr).subscribers.where(nick: "marklazz").build }
895909
end

0 commit comments

Comments
 (0)