Search code examples
ruby-on-railsrubyactiverecord

Best practice for similar repeated queries using ActiveRecord


I have a couple simple queries and I'm not sure what the best practice is.

I've written them in 2 ways which produce the same result. Which is preferred? Or is there a third, better way?

More concise:

Fruit.where(id: NOT_PREPACKAGED_RAW_FRUIT_IDS).update_all(prepackaged_raw_enabled: false)
Fruit.where.not(id: NOT_PREPACKAGED_RAW_FRUIT_IDS).update_all(prepackaged_raw_enabled: true)

More verbose:

fruits = Fruit.all
not_prepackaged = fruits.where(id: NOT_PREPACKAGED_RAW_FRUIT_IDS)
prepackaged = fruits - not_prepackaged
not_prepackaged.update_all(prepackaged_raw_enabled: false)
prepackaged.update_all(prepackaged_raw_enabled: true)

The purpose of the snippet is to do a onetime backfill.


Solution

  • If you want to do it in a single statement/query, you can write it like this:

    Fruit.update_all(prepackaged_raw_enabled:
      Fruit.arel_table[:id].not_in(NOT_PREPACKAGED_RAW_FRUIT_IDS)
    )
    

    If NOT_PREPACKAGED_RAW_FRUIT_IDS is [571, 572], then the statement would translate to the following SQL, which will update all of the records at once:

    UPDATE "fruits" 
    SET "prepackaged_raw_enabled" = "fruits"."id" NOT IN (571, 572)