【问题标题】:How to properly insert or update record in rails?如何在 Rails 中正确插入或更新记录?
【发布时间】:2015-05-06 22:59:51
【问题描述】:

显然,我看到all those questions 的回答如下:“使用find_or_create_by/initialize_by(<cols>)。”

问题是:“只是我,还是那些答案有点'破碎'?”如果有人要求插入或更新,通常意味着记录应该是唯一的:不应该存在两条匹配<cols> 的记录。按照这些答案,最终会在数据库中获得重复的行,或者偶尔会出现异常(如果使用唯一索引强制执行唯一性)。

为什么没有人建议这种方式?

begin
  Counter.create(name: '...', value: 1)
rescue ActiveRecord::RecordNotUnique
  Counter.where(name: '...').update_all('value = value + 1')
end

那是什么?我应该选择find_or_create_by/initialize_by 吗?还是我应该依赖 db 的唯一索引?在旁注中,我想不出任何人想要插入或更新 并且 可以有重复行的情况。

【问题讨论】:

  • 这是一个反问句吗?
  • 仅仅使用良好的验证不就满足了吗?请记住,rails 背后的概念是约定优于配置。如果没有必要,为什么要把事情复杂化?
  • @DavidHoelzer 因为验证受制于竞争条件,这就是为什么某些逻辑必须进入数据库的原因。
  • @HolgerJust 好吧,有点。我希望有人证明我错了。还没有发生。或者对。所以不是真正的修辞。

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


【解决方案1】:

因为begin...rescue 不应该用于此。

begin...rescue 用于发生错误情况时。

这是来自Ruby Learning 的示例。

def inverse(x)  
  raise ArgumentError, 'Argument is not numeric' unless x.is_a? Numeric  
  1.0 / x  
end

您的重复记录示例并不是真正的“错误”,因为每当提交重复数据时都会发生这种情况。

find_or_create_by 优雅地处理这两种情况,没有“错误条件”的概念。

【讨论】:

  • 但是违反数据库中的唯一约束错误。仅仅因为某事在某一层面上是错误并不意味着它必须在所有层面上都是错误。顺便说一句,find_or_create_by 只是 find_by(...) || create(...),所以它仍然受制于竞争条件,documentation 甚至建议在需要唯一性时将其包装在异常处理程序中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-21
  • 2021-10-16
  • 1970-01-01
  • 1970-01-01
  • 2015-08-14
  • 2010-12-29
相关资源
最近更新 更多