TL; DR:在AR :: Base保存事务中插入重复的连接表记录失败(由于唯一约束)导致保存失败和回滚.不添加重复的连接表记录是好的.不节约是坏事.
我正在将一个mysql应用程序迁移到postgres …我曾经在MysqL-land中遵循这样的模式将连接表记录添加到DB:
class EventsSeries < ActiveRecord::Base # UNIQUE KEY `index_events_series_on_event_id_and_series_id` (`event_id`,`series_id`) belongs_to :event belongs_to :series end class Series < ActiveRecord::Base has_many :events_series before_validation :add_new_event private def add_new_event # boils down to something like this EventSeries.new.tap do |es| es.event_id = 1 es.series_id = 1 begin es.save! rescue ActiveRecord::RecordNotUnique # Great it exists # this isn't really a problem # please move on end end end end
像这样调用:
Series.first.save # should not blow up on duplicate join record,cause i don't care
然而,postgres在这上面爆发了.这里有一个很好的解释:
http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html
…在“异常处理和回滚”部分(请参阅警告)
基本上#save启动一个事务,并且重复记录插入导致数据库异常,这使#saving的事务无效,这是悲伤的.
有没有更好的模式可以用于postgres-land?
谢谢!
编辑:
我坚信将这个逻辑保留在Series的保存事务中是有意义的……模式看起来像这样:
s = Series.new s.new_event_id = 123 # this is just an attr_accessor s.save # callbacks on Series kNow how to add the new event.
…它使我的控制器超小.
解决方法
如果您在事务内部并且要从错误中恢复并避免使整个事务无效,则必须使用保存点.
当您使用命令SAVEPOINT some-label时,您可以稍后运行命令ROLLBACK TO SAVEPOINT some-label以返回到事务中的该状态,并忽略保存点获取后的所有操作(包括错误).
请在Continuing a transaction after primary key violation error查看我的其他答案,以获得更多解释.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。