activerecord-update 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ea8267a673e2b98e469272b396c95715d72293a0
4
- data.tar.gz: 758e3c003b4711eb333f99dc89488a9f84dbf6e0
3
+ metadata.gz: c2f6991302388163951e76a30a77490613974ad6
4
+ data.tar.gz: 69c7913ae32b9b2be3ead5c5570fdad080cc425b
5
5
  SHA512:
6
- metadata.gz: 6bd413d5d665399e192852db292c1624ea7d6b5e95ab86bc4956aeb5ad56a1aec83f3c1ecb6c4920f1628fdb07892ddbf39e68d46d571bb92552f01fc427bf2a
7
- data.tar.gz: 65ffd2ccf31fab618f5cf5e316691321cbeebdaf33a785a495c1db51f3b2a75658c95a9f5d16092c3b4b141bdc4d958a036897b45461172b34cf8a48f1092184
6
+ metadata.gz: 05c28fe52389d585a66a5e4818c8849c5203a1a53db2399468f84c0449d3ffe1412b3e8604df679ef749eebd65d4eea05bbc14e5fba409af5ef42cbd2f049f4a
7
+ data.tar.gz: c1ff81888f193ac6477339581a97d93de28ed838ff09f43f312ace5718e5ef275a7eaab903b42368bf44734d4f296f2e942d333daed5d403abc54343d08d12cb
@@ -14,3 +14,6 @@ Metrics/BlockLength:
14
14
  Exclude:
15
15
  - activerecord-update.gemspec
16
16
  - spec/**/*_spec.rb
17
+
18
+ Style/AlignParameters:
19
+ EnforcedStyle: with_fixed_indentation
@@ -98,6 +98,7 @@ module ActiveRecord
98
98
  private
99
99
 
100
100
  # rubocop:disable Metrics/MethodLength
101
+ # rubocop:disable Metrics/AbcSize
101
102
 
102
103
  # (see .update_records)
103
104
  #
@@ -109,9 +110,9 @@ module ActiveRecord
109
110
  #
110
111
  # @see .update_records
111
112
  def _update_records(
112
- records,
113
- raise_on_validation_failure:,
114
- raise_on_stale_objects:
113
+ records,
114
+ raise_on_validation_failure:,
115
+ raise_on_stale_objects:
115
116
  )
116
117
 
117
118
  changed = changed_records(records)
@@ -119,15 +120,28 @@ module ActiveRecord
119
120
  return build_result(valid, failed, []) if valid.empty?
120
121
 
121
122
  timestamp = current_time
122
- query = sql_for_update_records(valid, timestamp)
123
- ids = perform_update_records_query(query, primary_key)
124
- result = build_result(valid, failed, ids)
125
- validate_result(result, raise_on_stale_objects)
126
-
127
- update_timestamp(valid, timestamp)
128
- mark_changes_applied(valid)
129
- result
123
+ previous_lock_values = {}
124
+
125
+ begin
126
+ query = sql_for_update_records(valid, timestamp, previous_lock_values)
127
+ ids = perform_update_records_query(query, primary_key)
128
+ result = build_result(valid, failed, ids)
129
+ restore_lock(result.stale_objects, previous_lock_values)
130
+
131
+ successful_records = valid - result.stale_objects
132
+ update_timestamp(successful_records, timestamp)
133
+ mark_changes_applied(successful_records)
134
+
135
+ validate_result(result, raise_on_stale_objects)
136
+ result
137
+ # rubocop:disable Lint/RescueException
138
+ rescue Exception
139
+ # rubocop:enable Lint/RescueException
140
+ restore_lock(records, previous_lock_values)
141
+ raise
142
+ end
130
143
  end
144
+ # rubocop:enable Metrics/AbcSize
131
145
  # rubocop:enable Metrics/MethodLength
132
146
 
133
147
  # Returns the given records that are not new records and have changed.
@@ -210,12 +224,17 @@ module ActiveRecord
210
224
  # @param records [<ActiveRecord::Base>] the records that have changed
211
225
  # @param timestamp [Time] the timestamp used for the `updated_at` column
212
226
  #
227
+ # @param previous_lock_values [{ Integer => Integer }] on return, this
228
+ # hash will contain the record ID's mapping to the previous lock
229
+ # versions. In an error occurs this hash can be used to restore the lock
230
+ # attribute to its previous value.
231
+ #
213
232
  # @return the SQL query for the #{update_records} method
214
233
  #
215
234
  # @see #update_records
216
235
  # rubocop:disable Metrics/MethodLength
217
236
  # rubocop:disable Metrics/AbcSize
218
- def sql_for_update_records(records, timestamp)
237
+ def sql_for_update_records(records, timestamp, previous_lock_values)
219
238
  attributes = changed_attributes(records)
220
239
  quoted_changed_attributes = changed_attributes_for_sql(
221
240
  attributes, quoted_table_alias
@@ -223,7 +242,12 @@ module ActiveRecord
223
242
 
224
243
  attributes = all_attributes(attributes)
225
244
  casts = type_casts(attributes)
226
- values = changed_values(records, attributes, timestamp)
245
+ values = changed_values(
246
+ records,
247
+ attributes,
248
+ timestamp,
249
+ previous_lock_values
250
+ )
227
251
  quoted_values = values_for_sql(values)
228
252
  quoted_column_names = column_names_for_sql(attributes)
229
253
  template = build_sql_template
@@ -353,6 +377,7 @@ module ActiveRecord
353
377
  end
354
378
 
355
379
  # rubocop:disable Metrics/MethodLength
380
+ # rubocop:disable Metrics/AbcSize
356
381
 
357
382
  # Returns the values of the given records that have changed.
358
383
  #
@@ -390,11 +415,18 @@ module ActiveRecord
390
415
  #
391
416
  # @param updated_at [Time] the value of the updated_at column
392
417
  #
418
+ # @param previous_lock_values [{ Integer => Integer }] on return, this
419
+ # hash will contain the record ID's mapping to the previous lock
420
+ # versions. In an error occurs this hash can be used to restore the lock
421
+ # attribute to its previous value.
422
+ #
393
423
  # @return [<<Object>>] the changed values
394
424
  #
395
425
  # @raise [ArgumentError]
396
426
  # * if the given list of records or changed attributes is `nil` or empty
397
- def changed_values(records, changed_attributes, updated_at)
427
+ def changed_values(records, changed_attributes, updated_at,
428
+ previous_lock_values)
429
+
398
430
  raise ArgumentError, 'No changed records given' if records.blank?
399
431
 
400
432
  if changed_attributes.blank?
@@ -404,6 +436,10 @@ module ActiveRecord
404
436
  extract_changed_values = lambda do |record|
405
437
  previous_lock_value = increment_lock(record)
406
438
 
439
+ if locking_enabled?
440
+ previous_lock_values[record.id] = previous_lock_value
441
+ end
442
+
407
443
  # We're using `slice` instead of `changed_attributes` because we need
408
444
  # to include all the changed attributes from all the changed records
409
445
  # and not just the changed attributes for a given record.
@@ -417,11 +453,17 @@ module ActiveRecord
417
453
 
418
454
  records.map(&extract_changed_values)
419
455
  end
456
+ # rubocop:enable Metrics/AbcSize
420
457
  # rubocop:enable Metrics/MethodLength
421
458
 
422
459
  # Increments the lock column of the given record if locking is enabled.
423
460
  #
424
- # @param [ActiveRecord::Base] the record to update the lock column for
461
+ # @param record [ActiveRecord::Base] the record to update the lock column
462
+ # for
463
+ #
464
+ # @param operation [:decrement, :increment] the operation to perform,
465
+ # increment or decrement
466
+ #
425
467
  # @return [void]
426
468
  def increment_lock(record)
427
469
  return unless locking_enabled?
@@ -432,6 +474,27 @@ module ActiveRecord
432
474
  previous_lock_value
433
475
  end
434
476
 
477
+ # Restores the lock column of the given records to given values,
478
+ # if locking is enabled.
479
+ #
480
+ # @param records [<ActiveRecord::Base>] the records to restore the lock
481
+ # column on
482
+ #
483
+ # @param lock_values [{ Integer => Integer }] this hash contains the
484
+ # record ID's mapping to the lock values that should be restored.
485
+ #
486
+ # @return [void]
487
+ def restore_lock(records, lock_values)
488
+ return if !locking_enabled? || records.empty?
489
+ method_name = locking_column + '='
490
+
491
+ records.each do |record|
492
+ lock_value = lock_values[record.id]
493
+ next unless lock_value
494
+ record.send(method_name, lock_value)
495
+ end
496
+ end
497
+
435
498
  # Returns the values of the given records that have changed, formatted for
436
499
  # SQL.
437
500
  #
@@ -1,5 +1,5 @@
1
1
  module ActiveRecord
2
2
  module Update
3
- VERSION = '0.0.1'.freeze
3
+ VERSION = '0.0.2'.freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-update
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jacob Carlborg
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-01-26 00:00:00.000000000 Z
11
+ date: 2017-02-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord