【发布时间】:2011-06-09 09:29:39
【问题描述】:
ActiveRecord 有内置的 upsert 功能吗?我知道我可以自己写,但如果这样的东西已经存在,我显然不想写。
【问题讨论】:
标签: ruby-on-rails activerecord upsert
ActiveRecord 有内置的 upsert 功能吗?我知道我可以自己写,但如果这样的东西已经存在,我显然不想写。
【问题讨论】:
标签: ruby-on-rails activerecord upsert
rails 6 中有一个很棒的新功能:他们将 upsert 和 upsert_all 添加到 ActiveRecord
【讨论】:
Model.find_or_initialize 可能会做你想做的事。如果有意义的话,你可以用save 或update_attributes 链接它。
更多信息请关注Rails Guides。
【讨论】:
find_or_initialize 和save 之间的表,它将失败。
我刚刚遇到了这个库: https://github.com/seamusabshere/upsert
我还没有测试过,但看起来很有希望
【讨论】:
IMO Upsert 机制需要为每个模型进行自定义配置。
因此,最好的解决方案是为模型实现自定义 SQL 查询,例如
insert into <table> (<field_1>, ..., <field_n>)
values (<field_1_value>, ..., <field_n_value>)
on duplicate key update
field_x = field_x_value,
...
field_z = field_z_value;
【讨论】:
Rails 6 针对这种情况引入了 create_or_find_by https://github.com/rails/rails/pull/31989
对于大量记录,也可以使用https://github.com/zdennis/activerecord-import
例子:
Book.import [book], on_duplicate_key_update: [:title]
【讨论】:
还有Model.find_or_create
【讨论】:
我写了一篇关于我们如何实现这一目标的博文。看看here。
您必须编写一个活动记录扩展。它看起来像这样。
module ActiveRecordExtension
extend ActiveSupport::Concern
def self.upsert(attributes)
begin
create(attributes)
rescue ActiveRecord::RecordNotUnique, PG::UniqueViolation => e
find_by_primary_key(attributes['primary_key']).
update(attributes)
end
end
end
ActiveRecord::Base.send(:include, ActiveRecordExtension)
【讨论】: