From 7ae406a8101251c1800042a0bc72e62a2f64cb77 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Mon, 1 Jun 2020 22:07:34 +0900 Subject: [PATCH] Allow attribute aliases for `validates_uniqueness_of` For now, the target attribute allows attribute aliases, but `:scope`'s attribute does not, the cause is that the former use `read_attribute_for_validation`, but the latter does not. Unfortunately we cannot use `read_attribute_for_validation` in this case, it intentionally bypass custom attribute getter to allow #7072. To work both alias and #7072, `read_attribute` should be used to resolve attribute aliases. --- .../active_record/validations/uniqueness.rb | 2 +- .../validations/uniqueness_validation_test.rb | 19 +++++++++++++++++++ activerecord/test/models/reply.rb | 3 +++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/validations/uniqueness.rb b/activerecord/lib/active_record/validations/uniqueness.rb index 6a92fa32ee..ce5c9e4f31 100644 --- a/activerecord/lib/active_record/validations/uniqueness.rb +++ b/activerecord/lib/active_record/validations/uniqueness.rb @@ -78,7 +78,7 @@ module ActiveRecord scope_value = if record.class._reflect_on_association(scope_item) record.association(scope_item).reader else - 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 76163e3093..901e59f9ad 100644 --- a/activerecord/test/cases/validations/uniqueness_validation_test.rb +++ b/activerecord/test/cases/validations/uniqueness_validation_test.rb @@ -156,6 +156,25 @@ class UniquenessValidationTest < ActiveRecord::TestCase assert r3.valid?, "Saving r3" end + def test_validate_uniqueness_with_aliases + Reply.validates_uniqueness_of(:new_content, scope: :new_parent_id) + + t = Topic.create(title: "I'm unique!") + + r1 = t.replies.create(title: "r1", content: "hello world") + assert_predicate r1, :valid?, "Saving r1" + + r2 = t.replies.create(title: "r2", content: "hello world") + assert_not_predicate r2, :valid?, "Saving r2 first time" + + r2.content = "something else" + assert r2.save, "Saving r2 second time" + + t2 = Topic.create("title" => "I'm unique too!") + r3 = t2.replies.create(title: "r3", content: "hello world") + assert_predicate r3, :valid?, "Saving r3" + end + def test_validate_uniqueness_with_scope_invalid_syntax error = assert_raises(ArgumentError) do Reply.validates_uniqueness_of(:content, scope: { parent_id: false }) diff --git a/activerecord/test/models/reply.rb b/activerecord/test/models/reply.rb index 49536a02e1..3ca43b245a 100644 --- a/activerecord/test/models/reply.rb +++ b/activerecord/test/models/reply.rb @@ -10,6 +10,9 @@ class Reply < Topic scope :ordered, -> { Reply.order(:id) } + alias_attribute :new_content, :content + alias_attribute :new_parent_id, :parent_id + # Method on Kernel def self.open approved