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.
This commit is contained in:
Ryuta Kamizono 2020-06-01 22:07:34 +09:00
parent 926b3eab80
commit 7ae406a810
3 changed files with 23 additions and 1 deletions

View File

@ -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

View File

@ -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 })

View File

@ -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