Skip to content

Commit d244b50

Browse files
authored
Add update_on option to batch_update (#26)
1 parent 92f5523 commit d244b50

5 files changed

Lines changed: 30 additions & 5 deletions

File tree

.rubocop.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ Metrics/PerceivedComplexity:
2323
Metrics/BlockLength:
2424
Enabled: false
2525

26+
Metrics/ParameterLists:
27+
Enabled: false
28+
2629
Layout/LineLength:
2730
Enabled: false
2831

Gemfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: .
33
specs:
4-
activerecord_batch_update (1.2.0)
4+
activerecord_batch_update (1.3.0)
55
activerecord (>= 7.2)
66
activesupport (>= 7.2)
77

lib/activerecord_batch_update.rb

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,14 @@ module ActiveRecordBatchUpdate
1414
# which will re-insert the objects if they were deleted in another thread
1515

1616
module ClassMethods
17-
def batch_update(entries, columns:, batch_size: 100, validate: true, clear_attribute_changes: true)
17+
def batch_update(
18+
entries,
19+
columns:,
20+
update_on: primary_key,
21+
batch_size: 100,
22+
validate: true,
23+
clear_attribute_changes: true
24+
)
1825
batch_update_ensure_entries_are_same_class!(entries)
1926

2027
columns = column_names if columns == :all
@@ -24,13 +31,13 @@ def batch_update(entries, columns:, batch_size: 100, validate: true, clear_attri
2431
entries.each { _1.updated_at = Time.current } if has_attribute?('updated_at')
2532
entries.each(&:validate!) if validate
2633

27-
primary_keys = Array.wrap(primary_key).map(&:to_s)
34+
update_on = Array.wrap(update_on).map(&:to_s)
2835

2936
updated_count = batch_update_statements(
3037
entries.map do |entry|
31-
(primary_keys + (entry.changed & columns)).to_h { [_1, entry.read_attribute(_1)] }
38+
(update_on + (entry.changed & columns)).to_h { [_1, entry.read_attribute(_1)] }
3239
end,
33-
update_on: primary_keys,
40+
update_on: update_on,
3441
batch_size: batch_size
3542
).sum do |sql|
3643
connection.update(sql)

spec/activerecord_batch_update_spec.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,20 @@
321321
end
322322
end
323323

324+
context 'with a custom update_on' do
325+
let!(:cat1) { Cat.create!(name: 'Figaro', owner_name: 'Geppetto') }
326+
let!(:cat2) { Cat.create!(name: 'Garfield', owner_name: 'Jon Arbuckle') }
327+
328+
it 'matches records using the specified column instead of the primary key' do
329+
expect do
330+
cat1.name = 'Nala'
331+
cat2.name = 'Simba'
332+
Cat.batch_update([cat1, cat2], columns: :name, update_on: :owner_name)
333+
end.to change { cat1.reload.name }.to('Nala')
334+
.and(change { cat2.reload.name }.to('Simba'))
335+
end
336+
end
337+
324338
context 'when the entries are not the same class' do
325339
let(:dog) do
326340
Class.new do

spec/spec_helper.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
create_table :cats, force: true do |t|
2323
t.column :name, :string
2424
t.column :birthday, :date
25+
t.column :owner_name, :string
2526
t.column :bitcoin_address, :string
2627
t.column :updated_at, :timestamp
2728
t.column :created_at, :timestamp

0 commit comments

Comments
 (0)