Skip to content

Instantly share code, notes, and snippets.

@Aryk
Last active August 13, 2023 17:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Aryk/ea6d9bce063a502323e3f42910925159 to your computer and use it in GitHub Desktop.
Save Aryk/ea6d9bce063a502323e3f42910925159 to your computer and use it in GitHub Desktop.
Sequel batch update
# Belongs in the dataset_module.
#
# Sample usage:
#
# User.batch_update([[{full_name: "A"}, {full_name: "C"}], [{full_name: "B"}, {full_name: "D"}]])
# User.batch_update([[{id: 4}, {full_name: "C"}], [{id: 5}, {full_name: "D"}]])
#
# # Conditions will apply to all the updates.
# User.where { created_at < 1.month.ago }.qualify.
# batch_update([[{id: 4}, {full_name: "C"}], [{id: 5}, {full_name: "D"}]])
#
# Came from conversation with Jeremy Evans: https://groups.google.com/g/sequel-talk/c/XJFkSuEiZBk
def batch_update(data_lookup, return_sql: false, update_prefix: "set_")
if data_lookup.present?
lookup_columns, update_columns = data_lookup.first.map(&:keys)
add_update_prefix = -> (str) { :"#{update_prefix}#{str}" }
from, to = Sequel[:data], Sequel[first_source]
conditions = lookup_columns.each.with_object({}) { |col, h| h[to[col]] = from[col] }
updates = update_columns.each.with_object({}) { |col, h| h[col] = from[add_update_prefix[col]] }
values = data_lookup.map { |l, u| l.values + u.values }
from(
to.value.to_sym,
db.values(values).as(from.value.to_sym, [*lookup_columns, *update_columns.map(&add_update_prefix)])
).
where(conditions).
send(return_sql ? :update_sql : :update, updates)
else
return_sql ? nil : 0
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment