dynamoid 3.7.1 → 3.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +246 -244
  3. data/LICENSE.txt +2 -2
  4. data/README.md +134 -55
  5. data/SECURITY.md +17 -0
  6. data/dynamoid.gemspec +66 -0
  7. data/lib/dynamoid/adapter.rb +7 -9
  8. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/batch_get_item.rb +2 -2
  9. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/execute_statement.rb +62 -0
  10. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/item_updater.rb +29 -15
  11. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/middleware/limit.rb +3 -0
  12. data/lib/dynamoid/adapter_plugin/aws_sdk_v3.rb +73 -59
  13. data/lib/dynamoid/associations/single_association.rb +28 -9
  14. data/lib/dynamoid/components.rb +2 -3
  15. data/lib/dynamoid/criteria/chain.rb +13 -9
  16. data/lib/dynamoid/criteria.rb +6 -7
  17. data/lib/dynamoid/dirty.rb +60 -63
  18. data/lib/dynamoid/document.rb +42 -12
  19. data/lib/dynamoid/errors.rb +2 -0
  20. data/lib/dynamoid/fields.rb +19 -37
  21. data/lib/dynamoid/finders.rb +9 -4
  22. data/lib/dynamoid/indexes.rb +45 -40
  23. data/lib/dynamoid/loadable.rb +6 -1
  24. data/lib/dynamoid/log/formatter.rb +19 -4
  25. data/lib/dynamoid/persistence/import.rb +4 -1
  26. data/lib/dynamoid/persistence/inc.rb +66 -0
  27. data/lib/dynamoid/persistence/save.rb +52 -5
  28. data/lib/dynamoid/persistence/update_fields.rb +1 -1
  29. data/lib/dynamoid/persistence/update_validations.rb +1 -1
  30. data/lib/dynamoid/persistence/upsert.rb +1 -1
  31. data/lib/dynamoid/persistence.rb +149 -61
  32. data/lib/dynamoid/undumping.rb +18 -0
  33. data/lib/dynamoid/validations.rb +6 -0
  34. data/lib/dynamoid/version.rb +1 -1
  35. data/lib/dynamoid.rb +1 -0
  36. metadata +30 -50
@@ -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
@@ -112,8 +113,10 @@ module Dynamoid
112
113
 
113
114
  if created_successfuly && self.options[:expires]
114
115
  attribute = self.options[:expires][:field]
115
- Dynamoid.adapter.update_time_to_live(table_name, attribute)
116
+ Dynamoid.adapter.update_time_to_live(options[:table_name], attribute)
116
117
  end
118
+
119
+ self
117
120
  end
118
121
 
119
122
  # Deletes the table for the model.
@@ -122,8 +125,10 @@ module Dynamoid
122
125
  # is deleted completely.
123
126
  #
124
127
  # Subsequent method calls for the same table will be ignored.
128
+ # @return [Model class] self
125
129
  def delete_table
126
130
  Dynamoid.adapter.delete_table(table_name)
131
+ self
127
132
  end
128
133
 
129
134
  # @private
@@ -365,32 +370,31 @@ module Dynamoid
365
370
  #
366
371
  # User.inc('1', 'Tylor', age: 2)
367
372
  #
373
+ # It's an atomic operation it does not interfere with other write
374
+ # requests.
375
+ #
368
376
  # Uses efficient low-level +UpdateItem+ operation and does only one HTTP
369
377
  # request.
370
378
  #
371
379
  # Doesn't run validations and callbacks. Doesn't update +created_at+ and
372
380
  # +updated_at+ as well.
373
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
+ #
374
390
  # @param hash_key_value [Scalar value] hash key
375
391
  # @param range_key_value [Scalar value] range key (optional)
376
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
394
+ # @return [Model class] self
377
395
  def inc(hash_key_value, range_key_value = nil, counters)
378
- options = if range_key
379
- value_casted = TypeCasting.cast_field(range_key_value, attributes[range_key])
380
- value_dumped = Dumping.dump_field(value_casted, attributes[range_key])
381
- { range_key: value_dumped }
382
- else
383
- {}
384
- end
385
-
386
- Dynamoid.adapter.update_item(table_name, hash_key_value, options) do |t|
387
- counters.each do |k, v|
388
- value_casted = TypeCasting.cast_field(v, attributes[k])
389
- value_dumped = Dumping.dump_field(value_casted, attributes[k])
390
-
391
- t.add(k => value_dumped)
392
- end
393
- end
396
+ Inc.call(self, hash_key_value, range_key_value, counters)
397
+ self
394
398
  end
395
399
  end
396
400
 
@@ -400,16 +404,44 @@ module Dynamoid
400
404
  #
401
405
  # post.touch
402
406
  #
403
- # 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.
404
409
  #
405
- # user.touch(:last_login_at)
410
+ # user.touch(:last_login_at, :viewed_at)
406
411
  #
407
- # @param name [Symbol] attribute name to update (optional)
408
- def touch(name = nil)
409
- now = DateTime.now
410
- self.updated_at = now
411
- attributes[name] = now if name
412
- save
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.
417
+ #
418
+ # The method must be used on a persisted object, otherwise
419
+ # +Dynamoid::Errors::Error+ will be thrown.
420
+ #
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)
423
+ # @return [Dynamoid::Document] self
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
+
444
+ self
413
445
  end
414
446
 
415
447
  # Is this object persisted in DynamoDB?
@@ -476,18 +508,11 @@ module Dynamoid
476
508
  # @since 0.2.0
477
509
  def save(options = {})
478
510
  self.class.create_table(sync: true)
511
+ create_or_update = new_record? ? :create : :update
479
512
 
480
- @_touch_record = options[:touch]
481
-
482
- if new_record?
483
- run_callbacks(:create) do
484
- run_callbacks(:save) do
485
- Save.call(self)
486
- end
487
- end
488
- else
489
- run_callbacks(:save) do
490
- Save.call(self)
513
+ run_callbacks(:save) do
514
+ run_callbacks(create_or_update) do
515
+ Save.call(self, touch: options[:touch])
491
516
  end
492
517
  end
493
518
  end
@@ -532,21 +557,26 @@ module Dynamoid
532
557
  #
533
558
  # user.update_attribute(:last_name, 'Tylor')
534
559
  #
560
+ # Validation is skipped.
561
+ #
535
562
  # Raises a +Dynamoid::Errors::UnknownAttribute+ exception if any of the
536
563
  # attributes is not on the model
537
564
  #
538
565
  # @param attribute [Symbol] attribute name to update
539
566
  # @param value [Object] the value to assign it
540
567
  # @return [Dynamoid::Document] self
568
+ #
541
569
  # @since 0.2.0
542
570
  def update_attribute(attribute, value)
571
+ # final implementation is in the Dynamoid::Validation module
543
572
  write_attribute(attribute, value)
544
573
  save
574
+ self
545
575
  end
546
576
 
547
577
  # Update a model.
548
578
  #
549
- # Runs validation and callbacks. Reloads all attribute values.
579
+ # Doesn't run validation. Runs only +update+ callbacks. Reloads all attribute values.
550
580
  #
551
581
  # Accepts mandatory block in order to specify operations which will modify
552
582
  # attributes. Supports following operations: +add+, +delete+ and +set+.
@@ -555,7 +585,7 @@ module Dynamoid
555
585
  # collections if attribute is a collection (one of +array+, +set+ or
556
586
  # +map+).
557
587
  #
558
- # user.update do |t|
588
+ # user.update! do |t|
559
589
  # t.add(age: 1, followers_count: 5)
560
590
  # t.add(hobbies: ['skying', 'climbing'])
561
591
  # end
@@ -563,24 +593,28 @@ module Dynamoid
563
593
  # Operation +delete+ is applied to collection attribute types and
564
594
  # substructs one collection from another.
565
595
  #
566
- # user.update do |t|
596
+ # user.update! do |t|
567
597
  # t.delete(hobbies: ['skying'])
568
598
  # end
569
599
  #
570
600
  # Operation +set+ just changes an attribute value:
571
601
  #
572
- # user.update do |t|
602
+ # user.update! do |t|
573
603
  # t.set(age: 21)
574
604
  # end
575
605
  #
576
- # All the operations works like +ADD+, +DELETE+ and +PUT+ actions supported
606
+ # All the operations work like +ADD+, +DELETE+ and +PUT+ actions supported
577
607
  # by +AttributeUpdates+
578
608
  # {parameter}[https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LegacyConditionalParameters.AttributeUpdates.html]
579
609
  # of +UpdateItem+ operation.
580
610
  #
611
+ # It's an atomic operation. So adding or deleting elements in a collection
612
+ # or incrementing or decrementing a numeric field is atomic and does not
613
+ # interfere with other write requests.
614
+ #
581
615
  # Can update a model conditionaly:
582
616
  #
583
- # user.update(if: { age: 20 }) do |t|
617
+ # user.update!(if: { age: 20 }) do |t|
584
618
  # t.add(age: 1)
585
619
  # end
586
620
  #
@@ -593,15 +627,24 @@ module Dynamoid
593
627
  # fail.
594
628
  #
595
629
  # @param conditions [Hash] Conditions on model attributes to make a conditional update (optional)
630
+ # @return [Dynamoid::Document] self
596
631
  def update!(conditions = {})
597
632
  run_callbacks(:update) do
598
- options = range_key ? { range_key: Dumping.dump_field(read_attribute(range_key), self.class.attributes[range_key]) } : {}
633
+ options = {}
634
+ if range_key
635
+ value = read_attribute(range_key)
636
+ attribute_options = self.class.attributes[range_key]
637
+ options[:range_key] = Dumping.dump_field(value, attribute_options)
638
+ end
599
639
 
600
640
  begin
601
- new_attrs = Dynamoid.adapter.update_item(self.class.table_name, hash_key, options.merge(conditions: conditions)) do |t|
641
+ table_name = self.class.table_name
642
+ update_item_options = options.merge(conditions: conditions)
643
+
644
+ new_attrs = Dynamoid.adapter.update_item(table_name, hash_key, update_item_options) do |t|
602
645
  t.add(lock_version: 1) if self.class.attributes[:lock_version]
603
646
 
604
- if Dynamoid::Config.timestamps
647
+ if self.class.timestamps_enabled?
605
648
  time_now = DateTime.now.in_time_zone(Time.zone)
606
649
  time_now_dumped = Dumping.dump_field(time_now, self.class.attributes[:updated_at])
607
650
  t.set(updated_at: time_now_dumped)
@@ -614,11 +657,13 @@ module Dynamoid
614
657
  raise Dynamoid::Errors::StaleObjectError.new(self, 'update')
615
658
  end
616
659
  end
660
+
661
+ self
617
662
  end
618
663
 
619
664
  # Update a model.
620
665
  #
621
- # Runs validation and callbacks. Reloads all attribute values.
666
+ # Doesn't run validation. Runs only +update+ callbacks. Reloads all attribute values.
622
667
  #
623
668
  # Accepts mandatory block in order to specify operations which will modify
624
669
  # attributes. Supports following operations: +add+, +delete+ and +set+.
@@ -639,6 +684,19 @@ module Dynamoid
639
684
  # t.delete(hobbies: ['skying'])
640
685
  # end
641
686
  #
687
+ # If it's applied to a scalar attribute then the item's attribute is
688
+ # removed at all:
689
+ #
690
+ # user.update do |t|
691
+ # t.delete(age: nil)
692
+ # end
693
+ #
694
+ # or even without useless value at all:
695
+ #
696
+ # user.update do |t|
697
+ # t.delete(:age)
698
+ # end
699
+ #
642
700
  # Operation +set+ just changes an attribute value:
643
701
  #
644
702
  # user.update do |t|
@@ -664,6 +722,7 @@ module Dynamoid
664
722
  # fail.
665
723
  #
666
724
  # @param conditions [Hash] Conditions on model attributes to make a conditional update (optional)
725
+ # @return [true|false] - whether conditions are met and updating is successful
667
726
  def update(conditions = {}, &block)
668
727
  update!(conditions, &block)
669
728
  true
@@ -696,14 +755,32 @@ module Dynamoid
696
755
  # user.increment!(:followers_count)
697
756
  # user.increment!(:followers_count, 2)
698
757
  #
699
- # 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])
700
769
  #
701
770
  # @param attribute [Symbol] attribute name
702
771
  # @param by [Numeric] value to add (optional)
703
- # @return [true|false] whether saved model successfully
704
- 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)
705
775
  increment(attribute, by)
706
- 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
707
784
  end
708
785
 
709
786
  # Change numeric attribute value.
@@ -718,9 +795,7 @@ module Dynamoid
718
795
  # @param by [Numeric] value to subtract (optional)
719
796
  # @return [Dynamoid::Document] self
720
797
  def decrement(attribute, by = 1)
721
- self[attribute] ||= 0
722
- self[attribute] -= by
723
- self
798
+ increment(attribute, -by)
724
799
  end
725
800
 
726
801
  # Change numeric attribute value and save a model.
@@ -731,14 +806,24 @@ module Dynamoid
731
806
  # user.decrement!(:followers_count)
732
807
  # user.decrement!(:followers_count, 2)
733
808
  #
734
- # 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])
735
820
  #
736
821
  # @param attribute [Symbol] attribute name
737
822
  # @param by [Numeric] value to subtract (optional)
738
- # @return [true|false] whether saved model successfully
739
- def decrement!(attribute, by = 1)
740
- decrement(attribute, by)
741
- 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)
742
827
  end
743
828
 
744
829
  # Delete a model.
@@ -748,9 +833,9 @@ module Dynamoid
748
833
  # Supports optimistic locking with the +lock_version+ attribute and doesn't
749
834
  # delete a model if it's already changed.
750
835
  #
751
- # Returns +true+ if deleted successfully and +false+ otherwise.
836
+ # Returns +self+ if deleted successfully and +false+ otherwise.
752
837
  #
753
- # @return [true|false] whether deleted successfully
838
+ # @return [Dynamoid::Document|false] whether deleted successfully
754
839
  # @since 0.2.0
755
840
  def destroy
756
841
  ret = run_callbacks(:destroy) do
@@ -783,6 +868,7 @@ module Dynamoid
783
868
  # Raises +Dynamoid::Errors::StaleObjectError+ exception if cannot delete a
784
869
  # model.
785
870
  #
871
+ # @return [Dynamoid::Document] self
786
872
  # @since 0.2.0
787
873
  def delete
788
874
  options = range_key ? { range_key: Dumping.dump_field(read_attribute(range_key), self.class.attributes[range_key]) } : {}
@@ -803,9 +889,11 @@ module Dynamoid
803
889
 
804
890
  Dynamoid.adapter.delete(self.class.table_name, hash_key, options)
805
891
 
806
- self.class.associations.each do |name, options|
892
+ self.class.associations.each do |name, _options|
807
893
  send(name).disassociate_source
808
894
  end
895
+
896
+ self
809
897
  rescue Dynamoid::Errors::ConditionalCheckFailedException
810
898
  raise Dynamoid::Errors::StaleObjectError.new(self, 'delete')
811
899
  end
@@ -236,9 +236,27 @@ module Dynamoid
236
236
  end
237
237
 
238
238
  class SerializedUndumper < Base
239
+ # We must use YAML.safe_load in Ruby 3.1 to handle serialized Set class
240
+ minimum_ruby_version = ->(version) { Gem::Version.new(RUBY_VERSION) >= Gem::Version.new(version) }
241
+ # Once we drop support for Rubies older than 2.6 we can remove this conditional (with major version bump)!
242
+ # YAML_SAFE_LOAD = minimum_ruby_version.call("2.6")
243
+ # But we don't want to change behavior for Ruby <= 3.0 that has been using the gem, without a major version bump
244
+ YAML_SAFE_LOAD = minimum_ruby_version.call('3.1')
245
+
239
246
  def process(value)
240
247
  if @options[:serializer]
241
248
  @options[:serializer].load(value)
249
+ elsif YAML_SAFE_LOAD
250
+ # The classes listed in permitted classes are added to the default set of "safe loadable" classes.
251
+ # TrueClass
252
+ # FalseClass
253
+ # NilClass
254
+ # Integer
255
+ # Float
256
+ # String
257
+ # Array
258
+ # Hash
259
+ YAML.safe_load(value, permitted_classes: [Symbol, Set, Date, Time, DateTime])
242
260
  else
243
261
  YAML.load(value)
244
262
  end
@@ -38,6 +38,12 @@ module Dynamoid
38
38
  self
39
39
  end
40
40
 
41
+ def update_attribute(attribute, value)
42
+ write_attribute(attribute, value)
43
+ save(validate: false)
44
+ self
45
+ end
46
+
41
47
  module ClassMethods
42
48
  # Override validates_presence_of to handle false values as present.
43
49
  #
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dynamoid
4
- VERSION = '3.7.1'
4
+ VERSION = '3.9.0'
5
5
  end
data/lib/dynamoid.rb CHANGED
@@ -4,6 +4,7 @@ require 'aws-sdk-dynamodb'
4
4
  require 'delegate'
5
5
  require 'time'
6
6
  require 'securerandom'
7
+ require 'set'
7
8
  require 'active_support'
8
9
  require 'active_support/core_ext'
9
10
  require 'active_support/json'
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.7.1
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: 2021-06-30 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
@@ -69,16 +69,16 @@ dependencies:
69
69
  name: appraisal
70
70
  requirement: !ruby/object:Gem::Requirement
71
71
  requirements:
72
- - - "~>"
72
+ - - ">="
73
73
  - !ruby/object:Gem::Version
74
- version: '2.2'
74
+ version: '0'
75
75
  type: :development
76
76
  prerelease: false
77
77
  version_requirements: !ruby/object:Gem::Requirement
78
78
  requirements:
79
- - - "~>"
79
+ - - ">="
80
80
  - !ruby/object:Gem::Version
81
- version: '2.2'
81
+ version: '0'
82
82
  - !ruby/object:Gem::Dependency
83
83
  name: bundler
84
84
  requirement: !ruby/object:Gem::Requirement
@@ -93,34 +93,20 @@ 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.8'
103
- type: :development
104
- prerelease: false
105
- version_requirements: !ruby/object:Gem::Requirement
106
- requirements:
107
- - - "~>"
108
- - !ruby/object:Gem::Version
109
- version: '0.8'
110
96
  - !ruby/object:Gem::Dependency
111
97
  name: pry
112
98
  requirement: !ruby/object:Gem::Requirement
113
99
  requirements:
114
100
  - - "~>"
115
101
  - !ruby/object:Gem::Version
116
- version: 0.12.0
102
+ version: '0.14'
117
103
  type: :development
118
104
  prerelease: false
119
105
  version_requirements: !ruby/object:Gem::Requirement
120
106
  requirements:
121
107
  - - "~>"
122
108
  - !ruby/object:Gem::Version
123
- version: 0.12.0
109
+ version: '0.14'
124
110
  - !ruby/object:Gem::Dependency
125
111
  name: rake
126
112
  requirement: !ruby/object:Gem::Requirement
@@ -141,63 +127,49 @@ dependencies:
141
127
  requirements:
142
128
  - - "~>"
143
129
  - !ruby/object:Gem::Version
144
- version: '3.9'
130
+ version: '3.12'
145
131
  type: :development
146
132
  prerelease: false
147
133
  version_requirements: !ruby/object:Gem::Requirement
148
134
  requirements:
149
135
  - - "~>"
150
136
  - !ruby/object:Gem::Version
151
- version: '3.9'
152
- - !ruby/object:Gem::Dependency
153
- name: rubocop
154
- requirement: !ruby/object:Gem::Requirement
155
- requirements:
156
- - - ">="
157
- - !ruby/object:Gem::Version
158
- version: '0'
159
- type: :development
160
- prerelease: false
161
- version_requirements: !ruby/object:Gem::Requirement
162
- requirements:
163
- - - ">="
164
- - !ruby/object:Gem::Version
165
- version: '0'
137
+ version: '3.12'
166
138
  - !ruby/object:Gem::Dependency
167
- name: wwtd
139
+ name: rubocop-lts
168
140
  requirement: !ruby/object:Gem::Requirement
169
141
  requirements:
170
142
  - - "~>"
171
143
  - !ruby/object:Gem::Version
172
- version: '1.4'
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: '1.4'
151
+ version: '10.0'
180
152
  - !ruby/object:Gem::Dependency
181
153
  name: yard
182
154
  requirement: !ruby/object:Gem::Requirement
183
155
  requirements:
184
- - - "~>"
156
+ - - ">="
185
157
  - !ruby/object:Gem::Version
186
- version: '0.9'
158
+ version: '0'
187
159
  type: :development
188
160
  prerelease: false
189
161
  version_requirements: !ruby/object:Gem::Requirement
190
162
  requirements:
191
- - - "~>"
163
+ - - ">="
192
164
  - !ruby/object:Gem::Version
193
- version: '0.9'
165
+ version: '0'
194
166
  description: Dynamoid is an ORM for Amazon's DynamoDB that supports offline development,
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
@@ -270,10 +246,14 @@ homepage: http://github.com/Dynamoid/dynamoid
270
246
  licenses:
271
247
  - MIT
272
248
  metadata:
249
+ homepage_uri: http://github.com/Dynamoid/dynamoid
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
273
252
  bug_tracker_uri: https://github.com/Dynamoid/dynamoid/issues
274
- changelog_uri: https://github.com/Dynamoid/dynamoid/tree/v3.7.1/CHANGELOG.md
275
- source_code_uri: https://github.com/Dynamoid/dynamoid/tree/v3.7.1
276
- documentation_uri: https://rubydoc.info/gems/dynamoid/3.7.1
253
+ documentation_uri: https://www.rubydoc.info/gems/dynamoid/3.9.0
254
+ funding_uri: https://opencollective.com/dynamoid
255
+ wiki_uri: https://github.com/Dynamoid/dynamoid/wiki
256
+ rubygems_mfa_required: 'true'
277
257
  post_install_message:
278
258
  rdoc_options: []
279
259
  require_paths:
@@ -289,7 +269,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
289
269
  - !ruby/object:Gem::Version
290
270
  version: '0'
291
271
  requirements: []
292
- rubygems_version: 3.2.3
272
+ rubygems_version: 3.4.6
293
273
  signing_key:
294
274
  specification_version: 4
295
275
  summary: Dynamoid is an ORM for Amazon's DynamoDB