如何在 Rails 5 个不同的 ActiveRecord 中验证相同的操作

How to validate in Rails 5 different ActiveRecord for the same action

我正在 Rails5 中构建一个身份验证系统,我有一个用户,我想检查其电子邮件字段的唯一性和正确格式。我已经看到这两个错误都引发了相同的异常,ActiveRecord::RecordInvalid,我想知道如何以一种良好而优雅的方式管理这两种情况。

这将是我的模型用户的重要部分:

validates_format_of :email, with: URI::MailTo::EMAIL_REGEXP
validates_presence_of :email
validates_uniqueness_of :email

这就是控制器:

begin
  user.save!
  render status: :created, json: { msg: 'User was created.' }
rescue ActiveRecord::RecordInvalid => err
  render status: conflict, json: { msg: err }
end

我想做的是区分唯一性错误(return 409)和格式错误(return 400)。

对于如何以更好的方式进行此检查的任何评论或帮助,我将不胜感激。

而不是做 user.save!,处理 user.save

if user.save
  render status: :created, json: { msg: 'User was created.' }
else
  render status: conflict, json: { msg: user.errors.full_messages.join(', ') }
end

bang 版本 (save!) 如果由于任何原因未保存对象会引发异常,而非 bang 版本 (save) returns true 如果对象被保存并且 false,如果没有。

为了进一步区分验证失败的类型,您可以使用#added?

user.errors.added? :email, :taken => 如果电子邮件唯一性错误则为真

user.errors.added? :email, :invalid => 如果电子邮件格式错误则为真。

捕获 ActiveRecord::RecordInvalid 异常不是处理这种情况的最佳方法。相反,我建议 运行 显式验证并检查 errors 对象。

检查 Rails API ActiveModel::Validations(https://api.rubyonrails.org/classes/ActiveModel/Validations.html#method-i-errors) and ActiveModel::Errors (https://api.rubyonrails.org/classes/ActiveModel/Errors.html) 的文档。

在 运行 宁 user.valid? 之后,您可以调查 user.errors 对象以检测确切类型的验证错误。然后您可以根据需要使用不同的响应代码进行回复:

if !user.valid?
  if user.errors[:email] == [" ... uniqueness error ..."]
    # return 409
  elsif user.errors[:email] == [" ... format error ..."]
    # return 400
  else
    # ...
  end
else
  user.save!
  # ...
end