什么是挽救异常并继续处理的正确方法?我有一个具有文件夹和项目的应用程序,通过名为folders_items的连接表具有habtm关系.该表具有唯一约束,确保没有重复的项目/文件夹组合.如果用户尝试多次将项目添加到同一文件夹,我显然不希望添加其他行;但我也不想停止处理.
当违反唯一约束时,Postgres会自动抛出异常,因此我尝试在控制器中忽略它,如下所示:
rescue PG::Error,:with => :do_nothing def do_nothing end
这在单次插入时工作正常.控制器执行渲染,状态代码为200.但是,我有另一种方法在循环中执行批量插入.在该方法中,控制器在遇到第一个重复行时退出循环,这不是我想要的.起初,我认为循环必须包含在正在回滚的事务中,但事实并非如此 – 重复之前的所有行都被插入.我希望它只是忽略约束异常并移动到下一个项目.如何防止PG :: Error异常中断此操作?
解决方法
通常,您的异常处理应该是最接近错误的点,您可以对异常做一些合理的事情.在您的情况下,您需要在循环中进行救援,例如:
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
几个兴趣点:
>数据库中的约束违规将为您提供ActiveRecord :: RecordNotUnique错误,而不是基础PG ::错误. AFAIK,如果你直接与数据库交谈而不是通过ActiveRecord,你会得到PG :: Error.>将INDEX_NAME_GOES_HERE替换为唯一索引的真实名称.>您只想忽略您期望的特定约束违规,因此下一个if(…)位后跟无争论加注(即如果它不是您期望看到的那样重新引发异常) ).