1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Fix uniqueness validation with an after_create hook.

record.id_was is nil in after_create/after_save, so we should use
id in these cases.

While this logic feels incomplete, the existing update_record uses the same
logic:
2fda4e0874/activerecord/lib/active_record/relation.rb (L83)

This logic was originally added for a similar problem:
updates not working with after_create hook.

See: 482f8c15b1

Followup to #23581
Fixes #23844
This commit is contained in:
Joe Rafaniello 2016-02-25 09:52:36 -05:00
parent 2fda4e0874
commit 0379da6abc
2 changed files with 19 additions and 1 deletions

View file

@ -18,7 +18,7 @@ module ActiveRecord
relation = build_relation(finder_class, table, attribute, value)
if record.persisted?
if finder_class.primary_key
relation = relation.where.not(finder_class.primary_key => record.id_was)
relation = relation.where.not(finder_class.primary_key => record.id_was || record.id)
else
raise UnknownPrimaryKey.new(finder_class, "Can not validate uniqueness for persisted record without primary key.")
end

View file

@ -53,6 +53,14 @@ class CoolTopic < Topic
validates_uniqueness_of :id
end
class TopicWithAfterCreate < Topic
after_create :set_author
def set_author
update_attributes!(:author_name => "#{title} #{id}")
end
end
class UniquenessValidationTest < ActiveRecord::TestCase
INT_MAX_VALUE = 2147483647
@ -469,6 +477,16 @@ class UniquenessValidationTest < ActiveRecord::TestCase
assert t.save, "Should still save t as unique"
end
def test_validate_uniqueness_with_after_create_performing_save
TopicWithAfterCreate.validates_uniqueness_of(:title)
topic = TopicWithAfterCreate.create!(:title => "Title1")
assert topic.author_name.start_with?("Title1")
topic2 = TopicWithAfterCreate.new(:title => "Title1")
refute topic2.valid?
assert_equal(["has already been taken"], topic2.errors[:title])
end
def test_validate_uniqueness_uuid
skip unless current_adapter?(:PostgreSQLAdapter)
item = UuidItem.create!(uuid: SecureRandom.uuid, title: 'item1')