diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 35f7c158a604d3a096f6ed656cd7e79222f84f8c..64a0e22af238ddb6e8043aefa3ce893f0c0ce729 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,7 @@ +* Fix the uniqueness validation scope with a polymorphic association. + + *Sergey Alekseev* + * Raise ActiveRecord::RecordNotFound from collection `*_ids` setters for unknown IDs with a better error message. diff --git a/activerecord/lib/active_record/validations/uniqueness.rb b/activerecord/lib/active_record/validations/uniqueness.rb index bed93bfc267db83e9c4e2c03d9c2312c2c2e67d5..512fdadacccf75260d77b2faf080fa2a2dac8195 100644 --- a/activerecord/lib/active_record/validations/uniqueness.rb +++ b/activerecord/lib/active_record/validations/uniqueness.rb @@ -85,11 +85,10 @@ def build_relation(klass, attribute, value) # :nodoc: def scope_relation(record, relation) Array(options[:scope]).each do |scope_item| - if reflection = record.class._reflect_on_association(scope_item) - scope_value = record.send(reflection.foreign_key) - scope_item = reflection.foreign_key + scope_value = if record.class._reflect_on_association(scope_item) + record.association(scope_item).reader else - scope_value = record._read_attribute(scope_item) + record._read_attribute(scope_item) end relation = relation.where(scope_item => scope_value) end diff --git a/activerecord/test/cases/validations/uniqueness_validation_test.rb b/activerecord/test/cases/validations/uniqueness_validation_test.rb index 44b4e28777f2a4af9d3b9d136e2ebc0333513958..6d226385920b3299b74cd5b6f6434827f41ac161 100644 --- a/activerecord/test/cases/validations/uniqueness_validation_test.rb +++ b/activerecord/test/cases/validations/uniqueness_validation_test.rb @@ -6,6 +6,9 @@ require "models/event" require "models/dashboard" require "models/uuid_item" +require "models/author" +require "models/person" +require "models/essay" class Wizard < ActiveRecord::Base self.abstract_class = true @@ -163,6 +166,19 @@ def test_validate_uniqueness_with_object_scope assert !r2.valid?, "Saving r2 first time" end + def test_validate_uniqueness_with_polymorphic_object_scope + Essay.validates_uniqueness_of(:name, scope: :writer) + + a = Author.create(name: "Sergey") + p = Person.create(first_name: "Sergey") + + e1 = a.essays.create(name: "Essay") + assert e1.valid?, "Saving e1" + + e2 = p.essays.create(name: "Essay") + assert e2.valid?, "Saving e2" + end + def test_validate_uniqueness_with_composed_attribute_scope r1 = ReplyWithTitleObject.create "title" => "r1", "content" => "hello world" assert r1.valid?, "Saving r1"