dynamoid 3.8.0 → 3.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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