我正在尝试找出一种优雅的方法来为我的所有ActiveRecord代码全局处理ActiveRecord::RecordNotUnique
异常。我知道validates_uniqueness_of
验证,但我想直接解救异常,因为我对数据库有约束,以避免因竞争条件导致的错误数据。我也不想创建一堆自定义方法,每次我想要保存或更新可能违反此约束的对象时直接处理异常。
我宁愿不修改像save()
那样的补丁ActiveRecord方法,但我开始认为在我的代码中为所有ActiveRecord对象实现优雅的异常处理可能需要这样做。下面是一些代码,用于演示解决方案的外观:
class Photo < ActiveRecord::Base
belongs_to :post
def save(*args)
super
rescue ActiveRecord::RecordNotUnique => error
errors[:base] << error.message
false
end
end
虽然如果我直接在Photo对象上调用save,但如果我使用带有accepts_nested_attributes_for
的{{1}}通过另一个模型保存对象,它将无法工作。
任何帮助都会得到很大的帮助。
由于
更新 理想的结果是处理异常,只需将键/值对添加到对象的错误哈希中,然后将表单错误显示给用户,告诉他们电子邮件已被删除。
答案 0 :(得分:2)
Action Controller Overview Rails指南中对此进行了介绍。简而言之,您可以使用rescue_from
方法为异常注册处理程序。如果您在ApplicationController中使用它,那么它将被所有其他控制器继承。
以下是指南中的示例:
class ApplicationController < ActionController::Base rescue_from ActiveRecord::RecordNotFound, with: :record_not_found private def record_not_found render plain: "404 Not Found", status: 404 end end
转到take a look了解更多信息和其他示例。
答案 1 :(得分:1)
在每个模型上定义关联时,我所寻找的是inverse_of
选项。 inverse_of
的作用是导致rails使用关联对象的内存实例而不是转到db来获取记录。我在Photo
模型中创建了一个看起来像这样的保存方法:
def save(*args)
super
rescue ActiveRecord::RecordNotUnique => error
post.errors[:base] << "You can only have one photo be your header photo"
false
end
在救援区中,当我拨打post.errors
时,我正在获取未保存的关联帖子对象,而不是基于photo.post_id
在数据库中寻找一个,因为这张照片为零对象无效,导致帖子不能持久保存到数据库。
以下是inverse_of
http://guides.rubyonrails.org/association_basics.html#bi-directional-associations