dynamoid 3.9.0 → 3.11.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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +26 -6
  3. data/README.md +202 -25
  4. data/dynamoid.gemspec +5 -6
  5. data/lib/dynamoid/adapter.rb +19 -13
  6. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/create_table.rb +2 -2
  7. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/filter_expression_convertor.rb +113 -0
  8. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/item_updater.rb +21 -2
  9. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/projection_expression_convertor.rb +40 -0
  10. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/query.rb +46 -61
  11. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/scan.rb +34 -28
  12. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/transact.rb +31 -0
  13. data/lib/dynamoid/adapter_plugin/aws_sdk_v3.rb +95 -66
  14. data/lib/dynamoid/associations/belongs_to.rb +6 -6
  15. data/lib/dynamoid/associations.rb +1 -1
  16. data/lib/dynamoid/components.rb +1 -0
  17. data/lib/dynamoid/config/options.rb +12 -12
  18. data/lib/dynamoid/config.rb +3 -0
  19. data/lib/dynamoid/criteria/chain.rb +149 -142
  20. data/lib/dynamoid/criteria/key_fields_detector.rb +6 -7
  21. data/lib/dynamoid/criteria/nonexistent_fields_detector.rb +2 -2
  22. data/lib/dynamoid/criteria/where_conditions.rb +36 -0
  23. data/lib/dynamoid/dirty.rb +87 -12
  24. data/lib/dynamoid/document.rb +1 -1
  25. data/lib/dynamoid/dumping.rb +38 -16
  26. data/lib/dynamoid/errors.rb +14 -2
  27. data/lib/dynamoid/fields/declare.rb +6 -6
  28. data/lib/dynamoid/fields.rb +6 -8
  29. data/lib/dynamoid/finders.rb +23 -32
  30. data/lib/dynamoid/indexes.rb +6 -7
  31. data/lib/dynamoid/loadable.rb +3 -2
  32. data/lib/dynamoid/persistence/inc.rb +6 -7
  33. data/lib/dynamoid/persistence/item_updater_with_casting_and_dumping.rb +36 -0
  34. data/lib/dynamoid/persistence/item_updater_with_dumping.rb +33 -0
  35. data/lib/dynamoid/persistence/save.rb +17 -18
  36. data/lib/dynamoid/persistence/update_fields.rb +7 -5
  37. data/lib/dynamoid/persistence/update_validations.rb +1 -1
  38. data/lib/dynamoid/persistence/upsert.rb +5 -4
  39. data/lib/dynamoid/persistence.rb +77 -21
  40. data/lib/dynamoid/transaction_write/base.rb +47 -0
  41. data/lib/dynamoid/transaction_write/create.rb +49 -0
  42. data/lib/dynamoid/transaction_write/delete_with_instance.rb +60 -0
  43. data/lib/dynamoid/transaction_write/delete_with_primary_key.rb +59 -0
  44. data/lib/dynamoid/transaction_write/destroy.rb +79 -0
  45. data/lib/dynamoid/transaction_write/save.rb +164 -0
  46. data/lib/dynamoid/transaction_write/update_attributes.rb +46 -0
  47. data/lib/dynamoid/transaction_write/update_fields.rb +102 -0
  48. data/lib/dynamoid/transaction_write/upsert.rb +96 -0
  49. data/lib/dynamoid/transaction_write.rb +464 -0
  50. data/lib/dynamoid/type_casting.rb +18 -15
  51. data/lib/dynamoid/undumping.rb +14 -3
  52. data/lib/dynamoid/validations.rb +1 -1
  53. data/lib/dynamoid/version.rb +1 -1
  54. data/lib/dynamoid.rb +7 -0
  55. metadata +30 -16
  56. data/lib/dynamoid/criteria/ignored_conditions_detector.rb +0 -41
  57. data/lib/dynamoid/criteria/overwritten_conditions_detector.rb +0 -40
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dynamoid
4
+ module Persistence
5
+ # @private
6
+ class ItemUpdaterWithDumping
7
+ def initialize(model_class, item_updater)
8
+ @model_class = model_class
9
+ @item_updater = item_updater
10
+ end
11
+
12
+ def add(attributes)
13
+ @item_updater.add(dump(attributes))
14
+ end
15
+
16
+ def set(attributes)
17
+ @item_updater.set(dump(attributes))
18
+ end
19
+
20
+ private
21
+
22
+ def dump(attributes)
23
+ dumped = {}
24
+
25
+ attributes.each do |name, value|
26
+ dumped[name] = Dumping.dump_field(value, @model_class.attributes[name])
27
+ end
28
+
29
+ dumped
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'item_updater_with_dumping'
4
+
3
5
  module Dynamoid
4
6
  module Persistence
5
7
  # @private
@@ -36,9 +38,10 @@ module Dynamoid
36
38
  attributes_to_persist = @model.attributes.slice(*@model.changed.map(&:to_sym))
37
39
 
38
40
  Dynamoid.adapter.update_item(@model.class.table_name, @model.hash_key, options_to_update_item) do |t|
41
+ item_updater = ItemUpdaterWithDumping.new(@model.class, t)
42
+
39
43
  attributes_to_persist.each do |name, value|
40
- value_dumped = Dumping.dump_field(value, @model.class.attributes[name])
41
- t.set(name => value_dumped)
44
+ item_updater.set(name => value)
42
45
  end
43
46
  end
44
47
  end
@@ -68,13 +71,11 @@ module Dynamoid
68
71
  end
69
72
 
70
73
  # Add an optimistic locking check if the lock_version column exists
71
- if @model.class.attributes[:lock_version]
72
- # Uses the original lock_version value from Dirty API
73
- # in case user changed 'lock_version' manually
74
- if @model.changes[:lock_version][0]
75
- conditions[:if] ||= {}
76
- conditions[:if][:lock_version] = @model.changes[:lock_version][0]
77
- end
74
+ # Uses the original lock_version value from Dirty API
75
+ # in case user changed 'lock_version' manually
76
+ if @model.class.attributes[:lock_version] && (@model.changes[:lock_version][0])
77
+ conditions[:if] ||= {}
78
+ conditions[:if][:lock_version] = @model.changes[:lock_version][0]
78
79
  end
79
80
 
80
81
  conditions
@@ -89,17 +90,15 @@ module Dynamoid
89
90
  end
90
91
 
91
92
  conditions = {}
92
- conditions[:if_exists] ||= {}
93
- conditions[:if_exists][@model.class.hash_key] = @model.hash_key
93
+ conditions[:if] ||= {}
94
+ conditions[:if][@model.class.hash_key] = @model.hash_key
94
95
 
95
96
  # Add an optimistic locking check if the lock_version column exists
96
- if @model.class.attributes[:lock_version]
97
- # Uses the original lock_version value from Dirty API
98
- # in case user changed 'lock_version' manually
99
- if @model.changes[:lock_version][0]
100
- conditions[:if] ||= {}
101
- conditions[:if][:lock_version] = @model.changes[:lock_version][0]
102
- end
97
+ # Uses the original lock_version value from Dirty API
98
+ # in case user changed 'lock_version' manually
99
+ if @model.class.attributes[:lock_version] && (@model.changes[:lock_version][0])
100
+ conditions[:if] ||= {}
101
+ conditions[:if][:lock_version] = @model.changes[:lock_version][0]
103
102
  end
104
103
 
105
104
  options[:conditions] = conditions
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'item_updater_with_casting_and_dumping'
4
+
3
5
  module Dynamoid
4
6
  module Persistence
5
7
  # @private
@@ -32,10 +34,10 @@ module Dynamoid
32
34
 
33
35
  def update_item
34
36
  Dynamoid.adapter.update_item(@model_class.table_name, @partition_key, options_to_update_item) do |t|
37
+ item_updater = ItemUpdaterWithCastingAndDumping.new(@model_class, t)
38
+
35
39
  @attributes.each do |k, v|
36
- value_casted = TypeCasting.cast_field(v, @model_class.attributes[k])
37
- value_dumped = Dumping.dump_field(value_casted, @model_class.attributes[k])
38
- t.set(k => value_dumped)
40
+ item_updater.set(k => v)
39
41
  end
40
42
  end
41
43
  end
@@ -54,8 +56,8 @@ module Dynamoid
54
56
  end
55
57
 
56
58
  conditions = @conditions.deep_dup
57
- conditions[:if_exists] ||= {}
58
- conditions[:if_exists][@model_class.hash_key] = @partition_key
59
+ conditions[:if] ||= {}
60
+ conditions[:if][@model_class.hash_key] = @partition_key
59
61
  options[:conditions] = conditions
60
62
 
61
63
  options
@@ -7,7 +7,7 @@ module Dynamoid
7
7
  def self.validate_attributes_exist(model_class, attributes)
8
8
  model_attributes = model_class.attributes.keys
9
9
 
10
- attributes.each do |attr_name, _|
10
+ attributes.each_key do |attr_name|
11
11
  unless model_attributes.include?(attr_name)
12
12
  raise Dynamoid::Errors::UnknownAttribute, "Attribute #{attr_name} does not exist in #{model_class}"
13
13
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'item_updater_with_casting_and_dumping'
4
+
3
5
  module Dynamoid
4
6
  module Persistence
5
7
  # @private
@@ -32,11 +34,10 @@ module Dynamoid
32
34
 
33
35
  def update_item
34
36
  Dynamoid.adapter.update_item(@model_class.table_name, @partition_key, options_to_update_item) do |t|
35
- @attributes.each do |k, v|
36
- value_casted = TypeCasting.cast_field(v, @model_class.attributes[k])
37
- value_dumped = Dumping.dump_field(value_casted, @model_class.attributes[k])
37
+ item_updater = ItemUpdaterWithCastingAndDumping.new(@model_class, t)
38
38
 
39
- t.set(k => value_dumped)
39
+ @attributes.each do |k, v|
40
+ item_updater.set(k => v)
40
41
  end
41
42
  end
42
43
  end
@@ -10,6 +10,7 @@ require 'dynamoid/persistence/upsert'
10
10
  require 'dynamoid/persistence/save'
11
11
  require 'dynamoid/persistence/inc'
12
12
  require 'dynamoid/persistence/update_validations'
13
+ require 'dynamoid/persistence/item_updater_with_dumping'
13
14
 
14
15
  # encoding: utf-8
15
16
  module Dynamoid
@@ -18,8 +19,9 @@ module Dynamoid
18
19
  module Persistence
19
20
  extend ActiveSupport::Concern
20
21
 
21
- attr_accessor :new_record
22
+ attr_accessor :new_record, :destroyed
22
23
  alias new_record? new_record
24
+ alias destroyed? destroyed
23
25
 
24
26
  # @private
25
27
  UNIX_EPOCH_DATE = Date.new(1970, 1, 1).freeze
@@ -166,7 +168,7 @@ module Dynamoid
166
168
 
167
169
  # Create a model.
168
170
  #
169
- # Initializes a new model and immediately saves it to DynamoDB.
171
+ # Initializes a new model and immediately saves it into DynamoDB.
170
172
  #
171
173
  # User.create(first_name: 'Mark', last_name: 'Tyler')
172
174
  #
@@ -174,7 +176,8 @@ module Dynamoid
174
176
  #
175
177
  # User.create([{ first_name: 'Alice' }, { first_name: 'Bob' }])
176
178
  #
177
- # Creates a model and pass it into a block to set other attributes.
179
+ # Instantiates a model and pass it into an optional block to set other
180
+ # attributes.
178
181
  #
179
182
  # User.create(first_name: 'Mark') do |u|
180
183
  # u.age = 21
@@ -182,7 +185,7 @@ module Dynamoid
182
185
  #
183
186
  # Validates model and runs callbacks.
184
187
  #
185
- # @param attrs [Hash|Array[Hash]] Attributes of the models
188
+ # @param attrs [Hash|Array<Hash>] Attributes of a model
186
189
  # @param block [Proc] Block to process a document after initialization
187
190
  # @return [Dynamoid::Document] The created document
188
191
  # @since 0.2.0
@@ -196,12 +199,28 @@ module Dynamoid
196
199
 
197
200
  # Create a model.
198
201
  #
199
- # Initializes a new object and immediately saves it to the Dynamoid.
202
+ # Initializes a new object and immediately saves it into DynamoDB.
203
+ #
204
+ # User.create!(first_name: 'Mark', last_name: 'Tyler')
205
+ #
200
206
  # Raises an exception +Dynamoid::Errors::DocumentNotValid+ if validation
201
- # failed. Accepts both Hash and Array of Hashes and can create several
207
+ # failed.
208
+ #
209
+ # Accepts both Hash and Array of Hashes and can create several
202
210
  # models.
203
211
  #
204
- # @param attrs [Hash|Array[Hash]] Attributes with which to create the object.
212
+ # User.create!([{ first_name: 'Alice' }, { first_name: 'Bob' }])
213
+ #
214
+ # Instantiates a model and pass it into an optional block to set other
215
+ # attributes.
216
+ #
217
+ # User.create!(first_name: 'Mark') do |u|
218
+ # u.age = 21
219
+ # end
220
+ #
221
+ # Validates model and runs callbacks.
222
+ #
223
+ # @param attrs [Hash|Array<Hash>] Attributes with which to create the object.
205
224
  # @param block [Proc] Block to process a document after initialization
206
225
  # @return [Dynamoid::Document] The created document
207
226
  # @since 0.2.0
@@ -271,7 +290,7 @@ module Dynamoid
271
290
  # meets the specified conditions. Conditions can be specified as a +Hash+
272
291
  # with +:if+ key:
273
292
  #
274
- # User.update_fields('1', { age: 26 }, if: { version: 1 })
293
+ # User.update_fields('1', { age: 26 }, { if: { version: 1 } })
275
294
  #
276
295
  # Here +User+ model has an integer +version+ field and the document will
277
296
  # be updated only if the +version+ attribute currently has value 1.
@@ -279,6 +298,13 @@ module Dynamoid
279
298
  # If a document with specified hash and range keys doesn't exist or
280
299
  # conditions were specified and failed the method call returns +nil+.
281
300
  #
301
+ # To check if some attribute (or attributes) isn't stored in a DynamoDB
302
+ # item (e.g. it wasn't set explicitly) there is another condition -
303
+ # +unless_exists+:
304
+ #
305
+ # user = User.create(name: 'Tylor')
306
+ # User.update_fields(user.id, { age: 18 }, { unless_exists: [:age] })
307
+ #
282
308
  # +update_fields+ uses the +UpdateItem+ operation so it saves changes and
283
309
  # loads an updated document back with one HTTP request.
284
310
  #
@@ -323,18 +349,25 @@ module Dynamoid
323
349
  # meets the specified conditions. Conditions can be specified as a +Hash+
324
350
  # with +:if+ key:
325
351
  #
326
- # User.upsert('1', { age: 26 }, if: { version: 1 })
352
+ # User.upsert('1', { age: 26 }, { if: { version: 1 } })
327
353
  #
328
354
  # Here +User+ model has an integer +version+ field and the document will
329
355
  # be updated only if the +version+ attribute currently has value 1.
330
356
  #
357
+ # To check if some attribute (or attributes) isn't stored in a DynamoDB
358
+ # item (e.g. it wasn't set explicitly) there is another condition -
359
+ # +unless_exists+:
360
+ #
361
+ # user = User.create(name: 'Tylor')
362
+ # User.upsert(user.id, { age: 18 }, { unless_exists: [:age] })
363
+ #
331
364
  # If conditions were specified and failed the method call returns +nil+.
332
365
  #
333
366
  # +upsert+ uses the +UpdateItem+ operation so it saves changes and loads
334
367
  # an updated document back with one HTTP request.
335
368
  #
336
369
  # Raises a +Dynamoid::Errors::UnknownAttribute+ exception if any of the
337
- # attributes is not on the model
370
+ # attributes is not declared in the model class.
338
371
  #
339
372
  # @param hash_key_value [Scalar value] hash key
340
373
  # @param range_key_value [Scalar value] range key (optional)
@@ -390,7 +423,7 @@ module Dynamoid
390
423
  # @param hash_key_value [Scalar value] hash key
391
424
  # @param range_key_value [Scalar value] range key (optional)
392
425
  # @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
426
+ # @option counters [true | Symbol | Array<Symbol>] :touch to update update_at attribute and optionally the specified ones
394
427
  # @return [Model class] self
395
428
  def inc(hash_key_value, range_key_value = nil, counters)
396
429
  Inc.call(self, hash_key_value, range_key_value, counters)
@@ -476,7 +509,7 @@ module Dynamoid
476
509
  #
477
510
  # +save+ by default sets timestamps attributes - +created_at+ and
478
511
  # +updated_at+ when creates new model and updates +updated_at+ attribute
479
- # when update already existing one.
512
+ # when updates already existing one.
480
513
  #
481
514
  # Changing +updated_at+ attribute at updating a model can be skipped with
482
515
  # +touch: false+ option:
@@ -507,7 +540,10 @@ module Dynamoid
507
540
  # @return [true|false] Whether saving successful or not
508
541
  # @since 0.2.0
509
542
  def save(options = {})
510
- self.class.create_table(sync: true)
543
+ if Dynamoid.config.create_table_on_save
544
+ self.class.create_table(sync: true)
545
+ end
546
+
511
547
  create_or_update = new_record? ? :create : :update
512
548
 
513
549
  run_callbacks(:save) do
@@ -518,7 +554,9 @@ module Dynamoid
518
554
  end
519
555
 
520
556
  # Update multiple attributes at once, saving the object once the updates
521
- # are complete. Returns +true+ if saving is successful and +false+
557
+ # are complete.
558
+ #
559
+ # Returns +true+ if saving is successful and +false+
522
560
  # otherwise.
523
561
  #
524
562
  # user.update_attributes(age: 27, last_name: 'Tylor')
@@ -618,6 +656,15 @@ module Dynamoid
618
656
  # t.add(age: 1)
619
657
  # end
620
658
  #
659
+ # To check if some attribute (or attributes) isn't stored in a DynamoDB
660
+ # item (e.g. it wasn't set explicitly) there is another condition -
661
+ # +unless_exists+:
662
+ #
663
+ # user = User.create(name: 'Tylor')
664
+ # user.update!(unless_exists: [:age]) do |t|
665
+ # t.set(age: 18)
666
+ # end
667
+ #
621
668
  # If a document doesn't meet conditions it raises
622
669
  # +Dynamoid::Errors::StaleObjectError+ exception.
623
670
  #
@@ -642,12 +689,12 @@ module Dynamoid
642
689
  update_item_options = options.merge(conditions: conditions)
643
690
 
644
691
  new_attrs = Dynamoid.adapter.update_item(table_name, hash_key, update_item_options) do |t|
645
- t.add(lock_version: 1) if self.class.attributes[:lock_version]
692
+ item_updater = ItemUpdaterWithDumping.new(self.class, t)
693
+
694
+ item_updater.add(lock_version: 1) if self.class.attributes[:lock_version]
646
695
 
647
696
  if self.class.timestamps_enabled?
648
- time_now = DateTime.now.in_time_zone(Time.zone)
649
- time_now_dumped = Dumping.dump_field(time_now, self.class.attributes[:updated_at])
650
- t.set(updated_at: time_now_dumped)
697
+ item_updater.set(updated_at: DateTime.now.in_time_zone(Time.zone))
651
698
  end
652
699
 
653
700
  yield t
@@ -714,6 +761,15 @@ module Dynamoid
714
761
  # t.add(age: 1)
715
762
  # end
716
763
  #
764
+ # To check if some attribute (or attributes) isn't stored in a DynamoDB
765
+ # item (e.g. it wasn't set explicitly) there is another condition -
766
+ # +unless_exists+:
767
+ #
768
+ # user = User.create(name: 'Tylor')
769
+ # user.update(unless_exists: [:age]) do |t|
770
+ # t.set(age: 18)
771
+ # end
772
+ #
717
773
  # If a document doesn't meet conditions it just returns +false+. Otherwise it returns +true+.
718
774
  #
719
775
  # It will increment the +lock_version+ attribute if a table has the column,
@@ -769,7 +825,7 @@ module Dynamoid
769
825
  #
770
826
  # @param attribute [Symbol] attribute name
771
827
  # @param by [Numeric] value to add (optional)
772
- # @param touch [true | Symbol | Array[Symbol]] to update update_at attribute and optionally the specified ones
828
+ # @param touch [true | Symbol | Array<Symbol>] to update update_at attribute and optionally the specified ones
773
829
  # @return [Dynamoid::Document] self
774
830
  def increment!(attribute, by = 1, touch: nil)
775
831
  increment(attribute, by)
@@ -820,7 +876,7 @@ module Dynamoid
820
876
  #
821
877
  # @param attribute [Symbol] attribute name
822
878
  # @param by [Numeric] value to subtract (optional)
823
- # @param touch [true | Symbol | Array[Symbol]] to update update_at attribute and optionally the specified ones
879
+ # @param touch [true | Symbol | Array<Symbol>] to update update_at attribute and optionally the specified ones
824
880
  # @return [Dynamoid::Document] self
825
881
  def decrement!(attribute, by = 1, touch: nil)
826
882
  increment!(attribute, -by, touch: touch)
@@ -889,7 +945,7 @@ module Dynamoid
889
945
 
890
946
  Dynamoid.adapter.delete(self.class.table_name, hash_key, options)
891
947
 
892
- self.class.associations.each do |name, _options|
948
+ self.class.associations.each_key do |name|
893
949
  send(name).disassociate_source
894
950
  end
895
951
 
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dynamoid
4
+ class TransactionWrite
5
+ class Base
6
+ # Callback called at "initialization" or "registration" an action
7
+ # before changes are persisted. It's a proper place to validate
8
+ # a model or run callbacks
9
+ def on_registration
10
+ raise 'Not implemented'
11
+ end
12
+
13
+ # Callback called after changes are persisted.
14
+ # It's a proper place to mark changes in a model as applied.
15
+ def on_commit
16
+ raise 'Not implemented'
17
+ end
18
+
19
+ # Callback called when a transaction is rolled back.
20
+ # It's a proper place to undo changes made in after_... callbacks.
21
+ def on_rollback
22
+ raise 'Not implemented'
23
+ end
24
+
25
+ # Whether some callback aborted or canceled an action
26
+ def aborted?
27
+ raise 'Not implemented'
28
+ end
29
+
30
+ # Whether there are changes to persist, e.g. updating a model with no
31
+ # attribute changed is skipped.
32
+ def skipped?
33
+ raise 'Not implemented'
34
+ end
35
+
36
+ # Value returned to a user as an action result
37
+ def observable_by_user_result
38
+ raise 'Not implemented'
39
+ end
40
+
41
+ # Coresponding part of a final request body
42
+ def action_request
43
+ raise 'Not implemented'
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ module Dynamoid
6
+ class TransactionWrite
7
+ class Create < Base
8
+ def initialize(model_class, attributes = {}, **options, &block)
9
+ super()
10
+
11
+ @model = model_class.new(attributes)
12
+
13
+ if block
14
+ yield(@model)
15
+ end
16
+
17
+ @save_action = Save.new(@model, **options)
18
+ end
19
+
20
+ def on_registration
21
+ @save_action.on_registration
22
+ end
23
+
24
+ def on_commit
25
+ @save_action.on_commit
26
+ end
27
+
28
+ def on_rollback
29
+ @save_action.on_rollback
30
+ end
31
+
32
+ def aborted?
33
+ @save_action.aborted?
34
+ end
35
+
36
+ def skipped?
37
+ false
38
+ end
39
+
40
+ def observable_by_user_result
41
+ @model
42
+ end
43
+
44
+ def action_request
45
+ @save_action.action_request
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ module Dynamoid
6
+ class TransactionWrite
7
+ class DeleteWithInstance < Base
8
+ def initialize(model)
9
+ super()
10
+
11
+ @model = model
12
+ @model_class = model.class
13
+ end
14
+
15
+ def on_registration
16
+ validate_model!
17
+ end
18
+
19
+ def on_commit
20
+ @model.destroyed = true
21
+ end
22
+
23
+ def on_rollback; end
24
+
25
+ def aborted?
26
+ false
27
+ end
28
+
29
+ def skipped?
30
+ false
31
+ end
32
+
33
+ def observable_by_user_result
34
+ @model
35
+ end
36
+
37
+ def action_request
38
+ key = { @model_class.hash_key => @model.hash_key }
39
+
40
+ if @model_class.range_key?
41
+ key[@model_class.range_key] = @model.range_value
42
+ end
43
+
44
+ {
45
+ delete: {
46
+ key: key,
47
+ table_name: @model_class.table_name
48
+ }
49
+ }
50
+ end
51
+
52
+ private
53
+
54
+ def validate_model!
55
+ raise Dynamoid::Errors::MissingHashKey if @model.hash_key.nil?
56
+ raise Dynamoid::Errors::MissingRangeKey if @model_class.range_key? && @model.range_value.nil?
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ module Dynamoid
6
+ class TransactionWrite
7
+ class DeleteWithPrimaryKey < Base
8
+ def initialize(model_class, hash_key, range_key)
9
+ super()
10
+
11
+ @model_class = model_class
12
+ @hash_key = hash_key
13
+ @range_key = range_key
14
+ end
15
+
16
+ def on_registration
17
+ validate_primary_key!
18
+ end
19
+
20
+ def on_commit; end
21
+
22
+ def on_rollback; end
23
+
24
+ def aborted?
25
+ false
26
+ end
27
+
28
+ def skipped?
29
+ false
30
+ end
31
+
32
+ def observable_by_user_result
33
+ nil
34
+ end
35
+
36
+ def action_request
37
+ key = { @model_class.hash_key => @hash_key }
38
+
39
+ if @model_class.range_key?
40
+ key[@model_class.range_key] = @range_key
41
+ end
42
+
43
+ {
44
+ delete: {
45
+ key: key,
46
+ table_name: @model_class.table_name
47
+ }
48
+ }
49
+ end
50
+
51
+ private
52
+
53
+ def validate_primary_key!
54
+ raise Dynamoid::Errors::MissingHashKey if @hash_key.nil?
55
+ raise Dynamoid::Errors::MissingRangeKey if @model_class.range_key? && @range_key.nil?
56
+ end
57
+ end
58
+ end
59
+ end