Book table
---
id: integer
author_name: string
title: string
用法:(输入rails c)
> Book.all #=> []
> Book.upsert({ id: 1, author_name: 'Liu', title: 'Tripple body 1'})
> Book.upsert({ id: 1, author_name: 'Liu', title: 'Tripple body 1'})
> Book.upsert({ id: 1, author_name: 'Liu', title: 'Tripple body 1'})
> Book.all # => only 1 book, with tile: 'Tripple body 1'
您可能会看到原始SQL如下所示:(在Postgres 14.2中)
INSERT INTO "books" ("author_name","title","created_at","updated_at")
VALUES ('Liu', 'Tripple body 1', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
ON CONFLICT ("id")
DO UPDATE SET updated_at=(
CASE WHEN (
"books"."author_name" IS NOT DISTINCT
FROM excluded."author_name"
AND "books"."title" IS NOT DISTINCT
FROM excluded."title"
)
THEN "books".updated_at ELSE CURRENT_TIMESTAMP END
),
"author_name"=excluded."author_name",
"title"=excluded."title"
RETURNING "id"
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)
8条答案
按热度按时间ubbxdtey1#
rails 6中有一个令人敬畏的新特性:他们把
upsert
和upsert_all
加到ActiveRecord
上更多信息请访问https://edgeapi.rubyonrails.org/classes/ActiveRecord/Persistence/ClassMethods.html#method-i-upsert_all
wlsrxk512#
Model.find_or_initialize
可能会做你想要的事情。如果有意义的话,你可以用save
或update_attributes
链接它。更多信息请参见导轨指南。
snz8szmq3#
我刚路过这个图书馆:https://github.com/seamusabshere/upsert
我还没测试过,但看起来很有希望
yduiuuwa4#
Rails 6为https://github.com/rails/rails/pull/31989引入了create_or_find_by
对于大量记录,也可以使用https://github.com/zdennis/activerecord-import
示例:
j2datikz5#
IMO Upsert机制需要为每个型号进行自定义配置。
因此,最好的解决方案是为模型实现自定义SQL查询,例如
rjee0c156#
还有模型.find_or_create
h9vpoimq7#
在Rails 6中,它有
upsert
方法,doc:用法:
用法:(输入
rails c
)您可能会看到原始SQL如下所示:(在Postgres 14.2中)
因此请注意:
upsert
将根据散列参数确定唯一性,因此请确保其中存在包含在表的唯一列中的键列(例如id
列)1.如果在参数中不传递
id
或类似的唯一列,则它总是将新记录插入到表中upsert
将跳过模型回调和验证。顺便说一句,我讨厌这种方法,我更喜欢
find_or_create_by
或只是:这就更清楚了。
z9zf31ra8#
我曾写过一篇博客文章,探讨如何实现这一目标,请查看here。
你必须写一个活动的记录扩展名,它看起来像这样。