轨道3忽略的Postgres唯一约束的例外 [英] Rails 3 ignore Postgres unique constraint exception

查看:268
本文介绍了轨道3忽略的Postgres唯一约束的例外的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

什么是抢救一个例外,只是继续处理的正确方法?我有一个应用程序,具有文件夹和项目,通过连接表称为folders_items一个HABTM关系。该表具有唯一约束,确保没有重复项/文件夹的组合。如果用户试图将项目添加到同一文件夹了好几次,我显然不希望其他行补充;但我不希望停止处理,无论是。

What's the correct way to rescue an exception and simply continue processing? I have an app that has Folders and Items, with a habtm relationship through a join table called folders_items. That table has a unique constraint ensuring that there are no duplicate item/folder combinations. If the user tries to add an item to the same folder several times, I obviously don't want the additional rows added; but I don't want to stop processing, either.

Postgres自动抛出时,唯一约束违反异常,所以我试图忽略它的控制器如下:

Postgres automatically throws an exception when the unique constraint is violated, so I tried to ignore it in the controller as follows:

rescue PG::Error, :with => :do_nothing

def do_nothing

end

这工作正常单插入。控制器执行渲染为200的状态code不过,我有做批量插入在一个循环中的另一种方法。在该方法中,控制器退出循环它遇到的第一个重复行的时候,这是不是我想要的。起初,我认为环一定是封装在天色回滚事务,但它不是 - 前重复的所有行得到插入。我希望它简单地忽略约束异常,并移动到下一个项目。我如何prevent的PG ::干扰这个错误异常?

This works fine on single insertions. The controller executes the render with a status code of 200. However, I have another method that does bulk inserts in a loop. In that method, the controller exits the loop when it encounters the first duplicate row, which is not what I want. At first, I thought that the loop must be getting wrapped in a transaction that's getting rolled back, but it isn't -- all the rows prior to the duplicate get inserted. I want it to simply ignore the constraint exception and move to the next item. How do I prevent the PG::Error exception from interrupting this?

推荐答案

在一般情况下,你的异常处理应在最近点,你可以做一些合理的与异常的错误。在你的情况,你会希望你的救援的循环中,例如:

In general, your exception handling should be at the closest point to the error that you can do something sensible with the exception. In your case, you'd want your rescue inside your loop, for example:

stuff.each do |h|
  begin
    Model.create(h)
  rescue ActiveRecord::RecordNotUnique => e
    next if(e.message =~ /unique.*constraint.*INDEX_NAME_GOES_HERE/)
    raise
  end
end

感兴趣的有两点:

  1. 在数据库里面一个约束冲突会给你一个的ActiveRecord :: RecordNotUnique 错误,而不是底层的 PG ::错误。 AFAIK,你会得到一个 PG ::错误如果你直接谈话的数据库,而不是通过ActiveRecord的。
  2. 替换 INDEX_NAME_GOES_HERE 的唯一索引的真实姓名。
  3. 您只需要忽略特定约束违规的你期待,因此接下来,如果(...)位随后argumentless (即重新抛出异常,如果它是你期待不看什么)。
  1. A constraint violation inside the database will give you an ActiveRecord::RecordNotUnique error rather than the underlying PG::Error. AFAIK, you'd get a PG::Error if you were talking directly to the database rather than going through ActiveRecord.
  2. Replace INDEX_NAME_GOES_HERE with the real name of the unique index.
  3. You only want to ignore the specific constraint violation the you're expecting, hence the next if(...) bit followed by the argumentless raise (i.e. re-raise the exception if it isn't what you're expecting to see).

这篇关于轨道3忽略的Postgres唯一约束的例外的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆