validation:如何检查特定错误

我知道如何检查属性是否有错误:

@post.errors[:title].any? 

是否可以检查哪个validation失败(例如“唯一性”)?

通过“采取”,我假设你的意思是标题已经存在于数据库中。 我进一步假设您的Post模型中有以下行:

 validates_uniqueness_of :title 

就个人而言,我认为通过检查validation错误来检查标题是否已经被采用将是脆弱的。 @post.errors[:title]将返回类似["has already been taken"] 。 但是,如果您决定更改错误消息或将应用程序国际化,该怎么办? 我认为你最好写一个方法来做测试:

 class Post < ActiveRecord::Base def title_unique? Post.where(:title => self.title).count == 0 end end 

那么你可以用@post.title_unique?测试标题是否是唯一的@post.title_unique? 。 如果已经有一个Rubygem动态地向ActiveRecord模型添加这样的方法,我不会感到惊讶。

最近我遇到了一个需要同样事情的情况:用户可以从一个表单一次添加/编辑多个记录。

由于在validation时并未将所有记录都写入数据库,因此无法使用@David的解决方案。 为了使事情变得更加复杂,数据库中已经存在的记录可能变为重复,这由唯一性validation器检测到。

TL; DR:您无法检查特定validation器 ,但可以检查特定错误

我正在使用这个:

 # The record has a duplicate value in `my_attribute`, detected by custom code. if my_attribute_is_not_unique? # Check if a previous uniqueness validator has already detected this: unless @record.errors.added?(:my_attribute, :taken) # No previous `:taken` error or at least a different text. @record.errors.add(:my_attribute, :taken) end end 

一些评论:

  • 它适用于I18n,但你必须提供相同的插值参数added? 正如之前的validation者所做的那样。
  • 如果先前的validation器已编写自定义消息而不是默认消息( :taken ),则此方法无效

如果您使用的是Rails 5+,则可以使用errors.details 。 对于早期的Rails版本,请使用backport gem: https : //github.com/cowbell/active_model-errors_details

 is_duplicate_title = @post.errors.details[:title].any? do |detail| detail[:error] == :uniqueness end 

Rails指南: http : //guides.rubyonrails.org/active_record_validations.html#working-with-validation-errors-errors-details