Back

rails - upsert 的使用解释:必须与id 配合才可以

发布时间: 2023-01-30 01:01:00

refer to : 

https://stackoverflow.com/questions/4695563/upsert-in-rails-activerecord

https://stackoverflow.com/questions/58759765/how-does-the-upsert-function-in-rails-work

https://apidock.com/rails/v6.0.0/ActiveRecord/Persistence/ClassMethods/upsert

作用: 根据传入的参数中的id, 来判断数据库中是否具备同样的id 的记录,如果存在则更新,如果不存在则插入.

例如: 有个model,  具备3个属性:  id,  author_name, title

[1] pry(main)> Book.all 

# => []      最开始时无记录

使用upsert:

原始过程为:

[2] pry(main)> Book.upsert author_name: '刘慈欣', title: '三体1'  // 可以看出报错了
ArgumentError: wrong number of arguments (given 0, expected 1)
from /home/siwei/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activerecord-7.0.4/lib/active_record/persistence.rb:222:in `upsert'
[3] pry(main)> Book.upsert {author_name: '刘慈欣', title: '三体1'}  // 还是报错
SyntaxError: unexpected ':', expecting '}'
Book.upsert {author_name: '刘慈欣', title: '三体1...
                        ^
SyntaxError: unexpected ',', expecting end-of-input
...sert {author_name: '刘慈欣', title: '三体1'}
...                              ^
[3] pry(main)> Book.upsert({author_name: '刘慈欣', title: '三体1'})  // 使用完整形式就没问题了。
  Book Upsert (3.4ms)  INSERT INTO "books" ("author_name","title","created_at","updated_at") VALUES ('刘慈欣', '三体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"
=> #<ActiveRecord::Result:0x00007f7f574e6050 @column_types={}, @columns=["id"], @hash_rows=nil, @rows=[[1]]>
[4] pry(main)> Book.all
  Book Load (0.9ms)  SELECT "books".* FROM "books"
=> [#<Book:0x00007f7f57498530
  id: 1,
  author_name: "刘慈欣",
  title: "三体1",
  created_at: Mon, 30 Jan 2023 08:59:28.514813000 CST +08:00,
  updated_at: Mon, 30 Jan 2023 08:59:28.514813000 CST +08:00>]

所以结论为:

1. upsert 传入的hash中,必须存在一个attribute, 对应数据库中的unique column

2. 该函数会跳过 model validation , call backs

Back