dynamoid 3.8.0 → 3.9.0

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.
@@ -8,6 +8,7 @@ require 'dynamoid/persistence/import'
8
8
  require 'dynamoid/persistence/update_fields'
9
9
  require 'dynamoid/persistence/upsert'
10
10
  require 'dynamoid/persistence/save'
11
+ require 'dynamoid/persistence/inc'
11
12
  require 'dynamoid/persistence/update_validations'
12
13
 
13
14
  # encoding: utf-8
@@ -378,28 +379,21 @@ module Dynamoid
378
379
  # Doesn't run validations and callbacks. Doesn't update +created_at+ and
379
380
  # +updated_at+ as well.
380
381
  #
382
+ # When `:touch` option is passed the timestamp columns are updating. If
383
+ # attribute names are passed, they are updated along with updated_at
384
+ # attribute:
385
+ #
386
+ # User.inc('1', age: 2, touch: true)
387
+ # User.inc('1', age: 2, touch: :viewed_at)
388
+ # User.inc('1', age: 2, touch: [:viewed_at, :accessed_at])
389
+ #
381
390
  # @param hash_key_value [Scalar value] hash key
382
391
  # @param range_key_value [Scalar value] range key (optional)
383
392
  # @param counters [Hash] value to increase by
393
+ # @option counters [true | Symbol | Array[Symbol]] :touch to update update_at attribute and optionally the specified ones
384
394
  # @return [Model class] self
385
395
  def inc(hash_key_value, range_key_value = nil, counters)
386
- options = if range_key
387
- value_casted = TypeCasting.cast_field(range_key_value, attributes[range_key])
388
- value_dumped = Dumping.dump_field(value_casted, attributes[range_key])
389
- { range_key: value_dumped }
390
- else
391
- {}
392
- end
393
-
394
- Dynamoid.adapter.update_item(table_name, hash_key_value, options) do |t|
395
- counters.each do |k, v|
396
- value_casted = TypeCasting.cast_field(v, attributes[k])
397
- value_dumped = Dumping.dump_field(value_casted, attributes[k])
398
-
399
- t.add(k => value_dumped)
400
- end
401
- end
402
-
396
+ Inc.call(self, hash_key_value, range_key_value, counters)
403
397
  self
404
398
  end
405
399
  end
@@ -410,17 +404,43 @@ module Dynamoid
410
404
  #
411
405
  # post.touch
412
406
  #
413
- # Can update another field in addition with the same timestamp if it's name passed as argument.
407
+ # Can update other fields in addition with the same timestamp if their
408
+ # names passed as arguments.
409
+ #
410
+ # user.touch(:last_login_at, :viewed_at)
411
+ #
412
+ # Some specific value can be used to save:
413
+ #
414
+ # user.touch(time: 1.hour.ago)
415
+ #
416
+ # No validation is performed and only +after_touch+ callback is called.
414
417
  #
415
- # user.touch(:last_login_at)
418
+ # The method must be used on a persisted object, otherwise
419
+ # +Dynamoid::Errors::Error+ will be thrown.
416
420
  #
417
- # @param name [Symbol] attribute name to update (optional)
421
+ # @param names [*Symbol] a list of attribute names to update (optional)
422
+ # @param time [Time] datetime value that can be used instead of the current time (optional)
418
423
  # @return [Dynamoid::Document] self
419
- def touch(name = nil)
420
- now = DateTime.now
421
- self.updated_at = now
422
- attributes[name] = now if name
423
- save
424
+ def touch(*names, time: nil)
425
+ if new_record?
426
+ raise Dynamoid::Errors::Error, 'cannot touch on a new or destroyed record object'
427
+ end
428
+
429
+ time_to_assign = time || DateTime.now
430
+
431
+ self.updated_at = time_to_assign
432
+ names.each do |name|
433
+ attributes[name] = time_to_assign
434
+ end
435
+
436
+ attribute_names = names.map(&:to_sym) + [:updated_at]
437
+ attributes_with_values = attributes.slice(*attribute_names)
438
+
439
+ run_callbacks :touch do
440
+ self.class.update_fields(hash_key, range_value, attributes_with_values)
441
+ clear_attribute_changes(attribute_names.map(&:to_s))
442
+ end
443
+
424
444
  self
425
445
  end
426
446
 
@@ -488,14 +508,11 @@ module Dynamoid
488
508
  # @since 0.2.0
489
509
  def save(options = {})
490
510
  self.class.create_table(sync: true)
491
-
492
- @_touch_record = options[:touch]
493
-
494
511
  create_or_update = new_record? ? :create : :update
495
512
 
496
- run_callbacks(create_or_update) do
497
- run_callbacks(:save) do
498
- Save.call(self)
513
+ run_callbacks(:save) do
514
+ run_callbacks(create_or_update) do
515
+ Save.call(self, touch: options[:touch])
499
516
  end
500
517
  end
501
518
  end
@@ -540,6 +557,8 @@ module Dynamoid
540
557
  #
541
558
  # user.update_attribute(:last_name, 'Tylor')
542
559
  #
560
+ # Validation is skipped.
561
+ #
543
562
  # Raises a +Dynamoid::Errors::UnknownAttribute+ exception if any of the
544
563
  # attributes is not on the model
545
564
  #
@@ -557,7 +576,7 @@ module Dynamoid
557
576
 
558
577
  # Update a model.
559
578
  #
560
- # Runs validation and callbacks. Reloads all attribute values.
579
+ # Doesn't run validation. Runs only +update+ callbacks. Reloads all attribute values.
561
580
  #
562
581
  # Accepts mandatory block in order to specify operations which will modify
563
582
  # attributes. Supports following operations: +add+, +delete+ and +set+.
@@ -644,7 +663,7 @@ module Dynamoid
644
663
 
645
664
  # Update a model.
646
665
  #
647
- # Runs validation and callbacks. Reloads all attribute values.
666
+ # Doesn't run validation. Runs only +update+ callbacks. Reloads all attribute values.
648
667
  #
649
668
  # Accepts mandatory block in order to specify operations which will modify
650
669
  # attributes. Supports following operations: +add+, +delete+ and +set+.
@@ -736,14 +755,32 @@ module Dynamoid
736
755
  # user.increment!(:followers_count)
737
756
  # user.increment!(:followers_count, 2)
738
757
  #
739
- # Returns +true+ if a model was saved and +false+ otherwise.
758
+ # Only `attribute` is saved. The model itself is not saved. So any other
759
+ # modified attributes will still be dirty. Validations and callbacks are
760
+ # skipped.
761
+ #
762
+ # When `:touch` option is passed the timestamp columns are updating. If
763
+ # attribute names are passed, they are updated along with updated_at
764
+ # attribute:
765
+ #
766
+ # user.increment!(:followers_count, touch: true)
767
+ # user.increment!(:followers_count, touch: :viewed_at)
768
+ # user.increment!(:followers_count, touch: [:viewed_at, :accessed_at])
740
769
  #
741
770
  # @param attribute [Symbol] attribute name
742
771
  # @param by [Numeric] value to add (optional)
743
- # @return [true|false] whether saved model successfully
744
- def increment!(attribute, by = 1)
772
+ # @param touch [true | Symbol | Array[Symbol]] to update update_at attribute and optionally the specified ones
773
+ # @return [Dynamoid::Document] self
774
+ def increment!(attribute, by = 1, touch: nil)
745
775
  increment(attribute, by)
746
- save
776
+ change = read_attribute(attribute) - (attribute_was(attribute) || 0)
777
+
778
+ run_callbacks :touch do
779
+ self.class.inc(hash_key, range_value, attribute => change, touch: touch)
780
+ clear_attribute_changes(attribute)
781
+ end
782
+
783
+ self
747
784
  end
748
785
 
749
786
  # Change numeric attribute value.
@@ -758,9 +795,7 @@ module Dynamoid
758
795
  # @param by [Numeric] value to subtract (optional)
759
796
  # @return [Dynamoid::Document] self
760
797
  def decrement(attribute, by = 1)
761
- self[attribute] ||= 0
762
- self[attribute] -= by
763
- self
798
+ increment(attribute, -by)
764
799
  end
765
800
 
766
801
  # Change numeric attribute value and save a model.
@@ -771,14 +806,24 @@ module Dynamoid
771
806
  # user.decrement!(:followers_count)
772
807
  # user.decrement!(:followers_count, 2)
773
808
  #
774
- # Returns +true+ if a model was saved and +false+ otherwise.
809
+ # Only `attribute` is saved. The model itself is not saved. So any other
810
+ # modified attributes will still be dirty. Validations and callbacks are
811
+ # skipped.
812
+ #
813
+ # When `:touch` option is passed the timestamp columns are updating. If
814
+ # attribute names are passed, they are updated along with updated_at
815
+ # attribute:
816
+ #
817
+ # user.decrement!(:followers_count, touch: true)
818
+ # user.decrement!(:followers_count, touch: :viewed_at)
819
+ # user.decrement!(:followers_count, touch: [:viewed_at, :accessed_at])
775
820
  #
776
821
  # @param attribute [Symbol] attribute name
777
822
  # @param by [Numeric] value to subtract (optional)
778
- # @return [true|false] whether saved model successfully
779
- def decrement!(attribute, by = 1)
780
- decrement(attribute, by)
781
- save
823
+ # @param touch [true | Symbol | Array[Symbol]] to update update_at attribute and optionally the specified ones
824
+ # @return [Dynamoid::Document] self
825
+ def decrement!(attribute, by = 1, touch: nil)
826
+ increment!(attribute, -by, touch: touch)
782
827
  end
783
828
 
784
829
  # Delete a model.
@@ -844,7 +889,7 @@ module Dynamoid
844
889
 
845
890
  Dynamoid.adapter.delete(self.class.table_name, hash_key, options)
846
891
 
847
- self.class.associations.each do |name, options|
892
+ self.class.associations.each do |name, _options|
848
893
  send(name).disassociate_source
849
894
  end
850
895
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dynamoid
4
- VERSION = '3.8.0'
4
+ VERSION = '3.9.0'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dynamoid
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.8.0
4
+ version: 3.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josh Symonds
@@ -21,7 +21,7 @@ authors:
21
21
  autorequire:
22
22
  bindir: bin
23
23
  cert_chain: []
24
- date: 2022-11-09 00:00:00.000000000 Z
24
+ date: 2023-04-13 00:00:00.000000000 Z
25
25
  dependencies:
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: activemodel
@@ -93,90 +93,62 @@ dependencies:
93
93
  - - ">="
94
94
  - !ruby/object:Gem::Version
95
95
  version: '0'
96
- - !ruby/object:Gem::Dependency
97
- name: coveralls
98
- requirement: !ruby/object:Gem::Requirement
99
- requirements:
100
- - - ">="
101
- - !ruby/object:Gem::Version
102
- version: '0'
103
- type: :development
104
- prerelease: false
105
- version_requirements: !ruby/object:Gem::Requirement
106
- requirements:
107
- - - ">="
108
- - !ruby/object:Gem::Version
109
- version: '0'
110
- - !ruby/object:Gem::Dependency
111
- name: overcommit
112
- requirement: !ruby/object:Gem::Requirement
113
- requirements:
114
- - - ">="
115
- - !ruby/object:Gem::Version
116
- version: '0'
117
- type: :development
118
- prerelease: false
119
- version_requirements: !ruby/object:Gem::Requirement
120
- requirements:
121
- - - ">="
122
- - !ruby/object:Gem::Version
123
- version: '0'
124
96
  - !ruby/object:Gem::Dependency
125
97
  name: pry
126
98
  requirement: !ruby/object:Gem::Requirement
127
99
  requirements:
128
100
  - - "~>"
129
101
  - !ruby/object:Gem::Version
130
- version: 0.12.0
102
+ version: '0.14'
131
103
  type: :development
132
104
  prerelease: false
133
105
  version_requirements: !ruby/object:Gem::Requirement
134
106
  requirements:
135
107
  - - "~>"
136
108
  - !ruby/object:Gem::Version
137
- version: 0.12.0
109
+ version: '0.14'
138
110
  - !ruby/object:Gem::Dependency
139
111
  name: rake
140
112
  requirement: !ruby/object:Gem::Requirement
141
113
  requirements:
142
- - - ">="
114
+ - - "~>"
143
115
  - !ruby/object:Gem::Version
144
- version: '0'
116
+ version: '13.0'
145
117
  type: :development
146
118
  prerelease: false
147
119
  version_requirements: !ruby/object:Gem::Requirement
148
120
  requirements:
149
- - - ">="
121
+ - - "~>"
150
122
  - !ruby/object:Gem::Version
151
- version: '0'
123
+ version: '13.0'
152
124
  - !ruby/object:Gem::Dependency
153
125
  name: rspec
154
126
  requirement: !ruby/object:Gem::Requirement
155
127
  requirements:
156
- - - ">="
128
+ - - "~>"
157
129
  - !ruby/object:Gem::Version
158
- version: '0'
130
+ version: '3.12'
159
131
  type: :development
160
132
  prerelease: false
161
133
  version_requirements: !ruby/object:Gem::Requirement
162
134
  requirements:
163
- - - ">="
135
+ - - "~>"
164
136
  - !ruby/object:Gem::Version
165
- version: '0'
137
+ version: '3.12'
166
138
  - !ruby/object:Gem::Dependency
167
- name: rubocop
139
+ name: rubocop-lts
168
140
  requirement: !ruby/object:Gem::Requirement
169
141
  requirements:
170
- - - '='
142
+ - - "~>"
171
143
  - !ruby/object:Gem::Version
172
- version: 0.81.0
144
+ version: '10.0'
173
145
  type: :development
174
146
  prerelease: false
175
147
  version_requirements: !ruby/object:Gem::Requirement
176
148
  requirements:
177
- - - '='
149
+ - - "~>"
178
150
  - !ruby/object:Gem::Version
179
- version: 0.81.0
151
+ version: '10.0'
180
152
  - !ruby/object:Gem::Dependency
181
153
  name: yard
182
154
  requirement: !ruby/object:Gem::Requirement
@@ -195,9 +167,9 @@ description: Dynamoid is an ORM for Amazon's DynamoDB that supports offline deve
195
167
  associations, querying, and everything else you'd expect from an ActiveRecord-style
196
168
  replacement.
197
169
  email:
170
+ - andry.konchin@gmail.com
198
171
  - peter.boling@gmail.com
199
172
  - brian@stellaservice.com
200
- - andry.konchin@gmail.com
201
173
  executables: []
202
174
  extensions: []
203
175
  extra_rdoc_files: []
@@ -205,11 +177,14 @@ files:
205
177
  - CHANGELOG.md
206
178
  - LICENSE.txt
207
179
  - README.md
180
+ - SECURITY.md
181
+ - dynamoid.gemspec
208
182
  - lib/dynamoid.rb
209
183
  - lib/dynamoid/adapter.rb
210
184
  - lib/dynamoid/adapter_plugin/aws_sdk_v3.rb
211
185
  - lib/dynamoid/adapter_plugin/aws_sdk_v3/batch_get_item.rb
212
186
  - lib/dynamoid/adapter_plugin/aws_sdk_v3/create_table.rb
187
+ - lib/dynamoid/adapter_plugin/aws_sdk_v3/execute_statement.rb
213
188
  - lib/dynamoid/adapter_plugin/aws_sdk_v3/item_updater.rb
214
189
  - lib/dynamoid/adapter_plugin/aws_sdk_v3/middleware/backoff.rb
215
190
  - lib/dynamoid/adapter_plugin/aws_sdk_v3/middleware/limit.rb
@@ -253,6 +228,7 @@ files:
253
228
  - lib/dynamoid/middleware/identity_map.rb
254
229
  - lib/dynamoid/persistence.rb
255
230
  - lib/dynamoid/persistence/import.rb
231
+ - lib/dynamoid/persistence/inc.rb
256
232
  - lib/dynamoid/persistence/save.rb
257
233
  - lib/dynamoid/persistence/update_fields.rb
258
234
  - lib/dynamoid/persistence/update_validations.rb
@@ -271,10 +247,11 @@ licenses:
271
247
  - MIT
272
248
  metadata:
273
249
  homepage_uri: http://github.com/Dynamoid/dynamoid
274
- source_code_uri: https://github.com/Dynamoid/dynamoid/tree/v3.8.0
275
- changelog_uri: https://github.com/Dynamoid/dynamoid/blob/v3.8.0/CHANGELOG.md
250
+ source_code_uri: https://github.com/Dynamoid/dynamoid/tree/v3.9.0
251
+ changelog_uri: https://github.com/Dynamoid/dynamoid/blob/v3.9.0/CHANGELOG.md
276
252
  bug_tracker_uri: https://github.com/Dynamoid/dynamoid/issues
277
- documentation_uri: https://www.rubydoc.info/gems/dynamoid/3.8.0
253
+ documentation_uri: https://www.rubydoc.info/gems/dynamoid/3.9.0
254
+ funding_uri: https://opencollective.com/dynamoid
278
255
  wiki_uri: https://github.com/Dynamoid/dynamoid/wiki
279
256
  rubygems_mfa_required: 'true'
280
257
  post_install_message:
@@ -292,7 +269,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
292
269
  - !ruby/object:Gem::Version
293
270
  version: '0'
294
271
  requirements: []
295
- rubygems_version: 3.2.32
272
+ rubygems_version: 3.4.6
296
273
  signing_key:
297
274
  specification_version: 4
298
275
  summary: Dynamoid is an ORM for Amazon's DynamoDB