ActiveRecord :: RecordNotUnique全局处理

时间:2014-12-08 20:57:05

标签: ruby-on-rails ruby postgresql rails-activerecord

我正在尝试找出一种优雅的方法来为我的所有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}}通过另一个模型保存对象,它将无法工作。

任何帮助都会得到很大的帮助。

由于

更新 理想的结果是处理异常,只需将键/值对添加到对象的错误哈希中,然后将表单错误显示给用户,告诉他们电子邮件已被删除。

2 个答案:

答案 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