validate :uniqueness_of_name
def uniqueness_of_name
existing_record = Model.find_by_name(name)
unless existing_record.nil?
errors.add(:name, "Record #{existing_record.id} already has the name #{name}")
end
end
validate :uniqueness_of_name
def uniqueness_of_name(current_record)
existing_record = Model.find_by_name(name)
unless existing_record.nil? || existing_record.id == current_record.id
errors.add(:name, "Record #{existing_record.id} already has the name #{name}")
end
end
validates :your_attribute, uniqueness: { message: ->(_object, data) do
other_object = Model.find_by(your_attribute: data[:value])
"#{data[:value]} is already taken by #{other_object.name}"
end }
6条答案
按热度按时间rkkpypqq1#
@vimsha的解决方案可能有效,但我发现了一种更简洁的方法,允许仍然使用
validates_uniqueness_of
,而不是创建自己的验证器:umuewwlo2#
试试像这样的东西
dldeef673#
@usha的唯一性验证代码在更新现有记录时会错误地失败,因为
Model.find_by_name(name)
会返回正在更新的记录。k5ifujac4#
对于使用新语法的Rails 5.0及更高版本,
更多详情:RoR文档。
lg40wkob5#
最初我认为你可以通过编写一个自定义验证器来解决这个问题,就像这样:
但是,我认为不可能像上面的例子那样访问
record
。validate_uniqueness_of
不会给予您对单个记录的访问权,直到在堆栈中很低的位置。最终,代码到达validate_each
,此时您可以访问单个记录。因此,您需要实现自己的validate_each
或扩展现有的validate_each
。在Rails中,默认情况下似乎没有办法做到这一点。当然,我很想知道是否有更好的方法:)
vmpqdwk36#
这并不是OP所追求的,但是我想在这里为那些只想在自定义验证错误消息中包含属性值的人添加这个。
在自定义消息中使用
%{value}
。大概是这样的:
这将导致一条类似“Joe已被带走”的消息。
根据文件:
具有动态属性值的消息。%{value}将替换为属性的实际值。%{attribute}和%{model}也可用。
从文档中可以看出,
%{attribute}
和%{model}
也可用。要获得不同的属性或执行更复杂的操作,您必须查看其他答案之一。