我正在使用Rails 6和新的upsert_all
方法。
这非常有用,但是,我有一些关于如何仅在新记录时才添加列的问题。以created_at
列为例。
如果记录是新的,您可能希望添加此列(以及任何其他null: false
列而不添加default: ...
但是,如果我正在更新,我也不想更改created_at
。
除了删除列之外,我将如何处理这个问题?
TLDR:使用unique_by
参数
由于upsert_all
不加载模型,为了以不同的方式处理某些行(即.db记录(,您需要使用unique_by
参数以及具有 unique_by 子句的数据库列。
完整示例
例如,假设我们有一个具有 id、名称和年龄的Book
模型。我想插入几本新书,并更新一本或多本书的年龄。name
列没有默认值,不能为 null。
# books table
# id: 1, name: 'dracula', age: 10
# id: 2, name: 'jane eyre', age: 20
# id: 3, name: 'ulysses', age: 30
我可以做:
Book.upsert_all([
{id: 2, age: 40}, # <- updates this record
{name: 'war and peace', age: 35 }, # <- new record
{name: '1984', age: 45} # <- new record
], unique_by: :id)
上面,请注意,我通过了unique_by: :id
论点。这指示数据库更新这些记录,而不是创建它们。
结果将是:
# books table
# id: 1, name: 'dracula', age: 10
# id: 2, name: 'jane eyre', age: 40
# id: 3, name: 'ulysses', age: 30
# id: 4, name: 'war and peace', age: 35
# id: 5, name: '1984', age: 45
我可以使用任何数据库列,只要它具有唯一索引(源(。例如,如果我在name
列上有一个唯一的索引,则此查询将给出类似的结果:
Book.upsert_all([
{name: 'jane eyre', age: 40}, # <- updates this record
{name: 'war and peace', age: 35 }, # <- new record
{name: '1984', age: 45} # <- new record
], unique_by: :name)
最后,Rails 将按预期处理updated_at
和created_at
属性。