Scenario

There is an existing Invoice model in the application. A new column is being introduced to add a Reference.

We must backfill all existing Invoices with a Reference.

Upsert all

Attempt to backfill using upsert_all. We want to update only the reference column on all Invoices, but leave all other columns untouched.

invoices = Invoice.where(reference: nil)
invoice_ids = invoices.pluck(:id)

upsert_attrs = invoice_ids.map do |invoice_id|
  {id: invoice_id, reference: generate_reference}
end

invoices.upsert_all(upsert_attrs, unique_by: :id)

This code produces an error of No unique index found for id

Expected

Before backfilling

idamountpaidnotesreference
1100.00true
2200.00trueReturned
3500.00falseDue end of month

After backfilling

idamountpaidnotesreference
1100.00trueX122791
2200.00trueReturnedAC12911
3500.00falseDue end of monthABI1000

Thoughts

It is unclear if this code block should work or if this is not the intended use case for upsert_all.

It could be an older issue on Rails 6.0.