907*_*7th 8 postgresql transactions ruby-on-rails upsert rails-activerecord
众所周知,Model.find_or_create_by(X)
实际上:
在步骤1和2之间可能存在争用条件.为了避免数据库中的X重复,应该在X的字段集上使用唯一索引.但是如果应用唯一索引,那么竞争事务之一将失败异常(尝试创建X的副本时).
如何实现"安全版本",#find_or_create_by
它永远不会引发任何异常并始终按预期工作?
答案在文档中
这是否是一个问题取决于应用程序的逻辑,但在行具有UNIQUE约束的特定情况下,可能会引发异常,只需重试:
Run Code Online (Sandbox Code Playgroud)begin CreditAccount.find_or_create_by(user_id: user.id) rescue ActiveRecord::RecordNotUnique retry end
解决方案1
您可以在模型中实施以下内容,或者如果您需要保持DRY,则可以在关注中实施
def self.find_or_create_by(*)
super
rescue ActiveRecord::RecordNotUnique
retry
end
Run Code Online (Sandbox Code Playgroud)
用法: Model.find_or_create_by(X)
解决方案2
或者,如果您不想覆盖find_or_create_by
,可以将以下内容添加到模型中
def self.safe_find_or_create_by(*args, &block)
find_or_create_by *args, &block
rescue ActiveRecord::RecordNotUnique
retry
end
Run Code Online (Sandbox Code Playgroud)
用法: Model.safe_find_or_create_by(X)
归档时间: |
|
查看次数: |
5834 次 |
最近记录: |