dynamoid 3.11.0 → 3.12.1
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 +4 -4
- data/CHANGELOG.md +25 -3
- data/README.md +93 -13
- data/lib/dynamoid/adapter_plugin/aws_sdk_v3.rb +8 -0
- data/lib/dynamoid/config.rb +1 -0
- data/lib/dynamoid/criteria/chain.rb +11 -3
- data/lib/dynamoid/dirty.rb +22 -11
- data/lib/dynamoid/dumping.rb +3 -3
- data/lib/dynamoid/errors.rb +16 -1
- data/lib/dynamoid/fields.rb +13 -3
- data/lib/dynamoid/finders.rb +38 -17
- data/lib/dynamoid/persistence/inc.rb +30 -13
- data/lib/dynamoid/persistence/save.rb +24 -12
- data/lib/dynamoid/persistence/update_fields.rb +18 -5
- data/lib/dynamoid/persistence/update_validations.rb +3 -3
- data/lib/dynamoid/persistence/upsert.rb +17 -4
- data/lib/dynamoid/persistence.rb +146 -11
- data/lib/dynamoid/transaction_read/find.rb +137 -0
- data/lib/dynamoid/transaction_read.rb +146 -0
- data/lib/dynamoid/transaction_write/delete_with_instance.rb +7 -2
- data/lib/dynamoid/transaction_write/delete_with_primary_key.rb +7 -2
- data/lib/dynamoid/transaction_write/destroy.rb +7 -2
- data/lib/dynamoid/transaction_write/item_updater.rb +55 -0
- data/lib/dynamoid/transaction_write/save.rb +7 -2
- data/lib/dynamoid/transaction_write/update_fields.rb +169 -32
- data/lib/dynamoid/transaction_write/upsert.rb +12 -2
- data/lib/dynamoid/transaction_write.rb +212 -3
- data/lib/dynamoid/validations.rb +7 -4
- data/lib/dynamoid/version.rb +1 -1
- data/lib/dynamoid.rb +1 -0
- metadata +8 -5
@@ -8,6 +8,7 @@ require 'dynamoid/transaction_write/save'
|
|
8
8
|
require 'dynamoid/transaction_write/update_fields'
|
9
9
|
require 'dynamoid/transaction_write/update_attributes'
|
10
10
|
require 'dynamoid/transaction_write/upsert'
|
11
|
+
require 'dynamoid/transaction_write/item_updater'
|
11
12
|
|
12
13
|
module Dynamoid
|
13
14
|
# The class +TransactionWrite+ provides means to perform multiple modifying
|
@@ -177,6 +178,26 @@ module Dynamoid
|
|
177
178
|
# When a model is not persisted - its id should have unique value.
|
178
179
|
# Otherwise a transaction will be rolled back.
|
179
180
|
#
|
181
|
+
# Raises +Dynamoid::Errors::MissingHashKey+ if a model is already persisted
|
182
|
+
# and a partition key has value +nil+ and raises
|
183
|
+
# +Dynamoid::Errors::MissingRangeKey+ if a sort key is required but has
|
184
|
+
# value +nil+.
|
185
|
+
#
|
186
|
+
# There are the following differences between transactional and
|
187
|
+
# non-transactional +#save!+:
|
188
|
+
# - transactional +#save!+ doesn't support the +:touch+ option
|
189
|
+
# - transactional +#save!+ doesn't support +lock_version+ attribute so it
|
190
|
+
# will not be incremented and will not be checked to detect concurrent
|
191
|
+
# modification of a model and +Dynamoid::Errors::StaleObjectError+
|
192
|
+
# exception will not be raised
|
193
|
+
# - transactional +#save!+ doesn't raise +Dynamoid::Errors::RecordNotUnique+
|
194
|
+
# at saving new model when primary key is already used. A generic
|
195
|
+
# +Aws::DynamoDB::Errors::TransactionCanceledException+ is raised instead.
|
196
|
+
# - transactional +save!+ doesn't raise
|
197
|
+
# +Dynamoid::Errors::StaleObjectError+ when a model that is being updated
|
198
|
+
# was concurrently deleted
|
199
|
+
# - a table isn't created lazily if it doesn't exist yet
|
200
|
+
#
|
180
201
|
# @param model [Dynamoid::Document] a model
|
181
202
|
# @param options [Hash] (optional)
|
182
203
|
# @option options [true|false] :validate validate a model or not - +true+ by default (optional)
|
@@ -215,6 +236,25 @@ module Dynamoid
|
|
215
236
|
# When a model is not persisted - its id should have unique value.
|
216
237
|
# Otherwise a transaction will be rolled back.
|
217
238
|
#
|
239
|
+
# Raises +Dynamoid::Errors::MissingHashKey+ if a model is already persisted
|
240
|
+
# and a partition key has value +nil+ and raises
|
241
|
+
# +Dynamoid::Errors::MissingRangeKey+ if a sort key is required but has
|
242
|
+
# value +nil+.
|
243
|
+
#
|
244
|
+
# There are the following differences between transactional and
|
245
|
+
# non-transactional +#save+:
|
246
|
+
# - transactional +#save+ doesn't support the +:touch+ option
|
247
|
+
# - transactional +#save+ doesn't support +lock_version+ attribute so it
|
248
|
+
# will not be incremented and will not be checked to detect concurrent
|
249
|
+
# modification of a model and +Dynamoid::Errors::StaleObjectError+
|
250
|
+
# exception will not be raised
|
251
|
+
# - transactional +#save+ doesn't raise +Dynamoid::Errors::RecordNotUnique+
|
252
|
+
# at saving new model when primary key is already used. A generic
|
253
|
+
# +Aws::DynamoDB::Errors::TransactionCanceledException+ is raised instead.
|
254
|
+
# - transactional +save+ doesn't raise +Dynamoid::Errors::StaleObjectError+
|
255
|
+
# when a model that is being updated was concurrently deleted
|
256
|
+
# - a table isn't created lazily if it doesn't exist yet
|
257
|
+
#
|
218
258
|
# @param model [Dynamoid::Document] a model
|
219
259
|
# @param options [Hash] (optional)
|
220
260
|
# @option options [true|false] :validate validate a model or not - +true+ by default (optional)
|
@@ -247,6 +287,20 @@ module Dynamoid
|
|
247
287
|
#
|
248
288
|
# Validates model and runs callbacks.
|
249
289
|
#
|
290
|
+
# Raises +Dynamoid::Errors::MissingRangeKey+ if a sort key is required but
|
291
|
+
# not specified or has value +nil+.
|
292
|
+
#
|
293
|
+
# There are the following differences between transactional and
|
294
|
+
# non-transactional +#create+:
|
295
|
+
# - transactional +#create!+ doesn't support +lock_version+ attribute so it
|
296
|
+
# will not be incremented and will not be checked to detect concurrent
|
297
|
+
# modification of a model and +Dynamoid::Errors::StaleObjectError+
|
298
|
+
# exception will not be raised
|
299
|
+
# - transactional +#create!+ doesn't raise +Dynamoid::Errors::RecordNotUnique+
|
300
|
+
# at saving new model when primary key is already used. A generic
|
301
|
+
# +Aws::DynamoDB::Errors::TransactionCanceledException+ is raised instead.
|
302
|
+
# - a table isn't created lazily if it doesn't exist yet
|
303
|
+
#
|
250
304
|
# @param model_class [Class] a model class which should be instantiated
|
251
305
|
# @param attributes [Hash|Array<Hash>] attributes of a model
|
252
306
|
# @param block [Proc] a block to process a model after initialization
|
@@ -286,6 +340,20 @@ module Dynamoid
|
|
286
340
|
#
|
287
341
|
# Validates model and runs callbacks.
|
288
342
|
#
|
343
|
+
# Raises +Dynamoid::Errors::MissingRangeKey+ if a sort key is required but
|
344
|
+
# not specified or has value +nil+.
|
345
|
+
#
|
346
|
+
# There are the following differences between transactional and
|
347
|
+
# non-transactional +#create+:
|
348
|
+
# - transactional +#create+ doesn't support +lock_version+ attribute so it
|
349
|
+
# will not be incremented and will not be checked to detect concurrent
|
350
|
+
# modification of a model and +Dynamoid::Errors::StaleObjectError+
|
351
|
+
# exception will not be raised
|
352
|
+
# - transactional +#create+ doesn't raise +Dynamoid::Errors::RecordNotUnique+
|
353
|
+
# at saving new model when primary key is already used. A generic
|
354
|
+
# +Aws::DynamoDB::Errors::TransactionCanceledException+ is raised instead.
|
355
|
+
# - a table isn't created lazily if it doesn't exist yet
|
356
|
+
#
|
289
357
|
# @param model_class [Class] a model class which should be instantiated
|
290
358
|
# @param attributes [Hash|Array<Hash>] attributes of a model
|
291
359
|
# @param block [Proc] a block to process a model after initialization
|
@@ -321,6 +389,17 @@ module Dynamoid
|
|
321
389
|
# Raises a +Dynamoid::Errors::UnknownAttribute+ exception if any of the
|
322
390
|
# attributes is not declared in the model class.
|
323
391
|
#
|
392
|
+
# Raises +Dynamoid::Errors::MissingHashKey+ if a partition key has value
|
393
|
+
# +nil+ and +Dynamoid::Errors::MissingRangeKey+ if a sort key is required
|
394
|
+
# but has value +nil+.
|
395
|
+
#
|
396
|
+
# There are the following differences between transactional and
|
397
|
+
# non-transactional +#upsert+:
|
398
|
+
# - transactional +#upsert+ doesn't support conditions (that's +if+ and
|
399
|
+
# +unless_exists+ options)
|
400
|
+
# - transactional +#upsert+ doesn't return a document that was updated or
|
401
|
+
# created
|
402
|
+
#
|
324
403
|
# @param model_class [Class] a model class
|
325
404
|
# @param hash_key [Scalar value] hash key value
|
326
405
|
# @param range_key [Scalar value] range key value (optional)
|
@@ -345,16 +424,79 @@ module Dynamoid
|
|
345
424
|
# t.update_fields(User, '1', 'Tylor', age: 26)
|
346
425
|
# end
|
347
426
|
#
|
427
|
+
# Updates can also be performed in a block.
|
428
|
+
#
|
429
|
+
# Dynamoid::TransactionWrite.execute do |t|
|
430
|
+
# t.update_fields(User, 1) do |u|
|
431
|
+
# u.add(article_count: 1)
|
432
|
+
# u.delete(favorite_colors: 'green')
|
433
|
+
# u.set(age: 27, last_name: 'Tylor')
|
434
|
+
# end
|
435
|
+
# end
|
436
|
+
#
|
437
|
+
# Operation +add+ just adds a value for numeric attributes and join
|
438
|
+
# collections if attribute is a set.
|
439
|
+
#
|
440
|
+
# t.update_fields(User, 1) do |u|
|
441
|
+
# u.add(age: 1, followers_count: 5)
|
442
|
+
# u.add(hobbies: ['skying', 'climbing'])
|
443
|
+
# end
|
444
|
+
#
|
445
|
+
# Operation +delete+ is applied to collection attribute types and
|
446
|
+
# substructs one collection from another.
|
447
|
+
#
|
448
|
+
# t.update_fields(User, 1) do |u|
|
449
|
+
# u.delete(hobbies: ['skying'])
|
450
|
+
# end
|
451
|
+
#
|
452
|
+
# Operation +set+ just changes an attribute value:
|
453
|
+
#
|
454
|
+
# t.update_fields(User, 1) do |u|
|
455
|
+
# u.set(age: 21)
|
456
|
+
# end
|
457
|
+
#
|
458
|
+
# Operation +remove+ removes one or more attributes from an item.
|
459
|
+
#
|
460
|
+
# t.update_fields(User, 1) do |u|
|
461
|
+
# u.remove(:age)
|
462
|
+
# end
|
463
|
+
#
|
464
|
+
# All the operations work like +ADD+, +DELETE+, +REMOVE+, and +SET+ actions supported
|
465
|
+
# by +UpdateExpression+
|
466
|
+
# {parameter}[https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html]
|
467
|
+
# of +UpdateItem+ operation.
|
468
|
+
#
|
469
|
+
# It's atomic operations. So adding or deleting elements in a collection
|
470
|
+
# or incrementing or decrementing a numeric field is atomic and does not
|
471
|
+
# interfere with other write requests.
|
472
|
+
#
|
348
473
|
# Raises a +Dynamoid::Errors::UnknownAttribute+ exception if any of the
|
349
474
|
# attributes is not declared in the model class.
|
350
475
|
#
|
476
|
+
# Raises +Dynamoid::Errors::MissingHashKey+ if a partition key has value
|
477
|
+
# +nil+ and +Dynamoid::Errors::MissingRangeKey+ if a sort key is required
|
478
|
+
# but has value +nil+.
|
479
|
+
#
|
480
|
+
# There are the following differences between transactional and
|
481
|
+
# non-transactional +#update_fields+:
|
482
|
+
# - transactional +#update_fields+ doesn't support conditions (that's +if+
|
483
|
+
# and +unless_exists+ options)
|
484
|
+
# - transactional +#update_fields+ doesn't return a document that was
|
485
|
+
# updated or created
|
486
|
+
#
|
351
487
|
# @param model_class [Class] a model class
|
352
488
|
# @param hash_key [Scalar value] hash key value
|
353
489
|
# @param range_key [Scalar value] range key value (optional)
|
354
490
|
# @param attributes [Hash]
|
355
491
|
# @return [nil]
|
356
|
-
def update_fields(model_class, hash_key, range_key = nil, attributes
|
357
|
-
|
492
|
+
def update_fields(model_class, hash_key, range_key = nil, attributes = nil, &block)
|
493
|
+
# given no attributes, but there may be a block
|
494
|
+
if range_key.is_a?(Hash) && !attributes
|
495
|
+
attributes = range_key
|
496
|
+
range_key = nil
|
497
|
+
end
|
498
|
+
|
499
|
+
action = Dynamoid::TransactionWrite::UpdateFields.new(model_class, hash_key, range_key, attributes, &block)
|
358
500
|
register_action action
|
359
501
|
end
|
360
502
|
|
@@ -367,6 +509,21 @@ module Dynamoid
|
|
367
509
|
# Returns +true+ if saving is successful and +false+
|
368
510
|
# otherwise.
|
369
511
|
#
|
512
|
+
# Raises +Dynamoid::Errors::MissingHashKey+ if a partition key has value
|
513
|
+
# +nil+ and raises +Dynamoid::Errors::MissingRangeKey+ if a sort key is
|
514
|
+
# required but has value +nil+.
|
515
|
+
#
|
516
|
+
# There are the following differences between transactional and
|
517
|
+
# non-transactional +#update_attributes+:
|
518
|
+
# - transactional +#update_attributes+ doesn't support +lock_version+ attribute so it
|
519
|
+
# will not be incremented and will not be checked to detect concurrent
|
520
|
+
# modification of a model and +Dynamoid::Errors::StaleObjectError+
|
521
|
+
# exception will not be raised
|
522
|
+
# - transactional +update_attributes+ doesn't raise
|
523
|
+
# +Dynamoid::Errors::StaleObjectError+ when a model that is being updated
|
524
|
+
# was concurrently deleted
|
525
|
+
# - a table isn't created lazily if it doesn't exist yet
|
526
|
+
#
|
370
527
|
# @param model [Dynamoid::Document] a model
|
371
528
|
# @param attributes [Hash] a hash of attributes to update
|
372
529
|
# @return [true|false] Whether updating successful or not
|
@@ -387,6 +544,21 @@ module Dynamoid
|
|
387
544
|
# Raises a +Dynamoid::Errors::DocumentNotValid+ exception if some vaidation
|
388
545
|
# fails.
|
389
546
|
#
|
547
|
+
# Raises +Dynamoid::Errors::MissingHashKey+ if a partition key has value
|
548
|
+
# +nil+ and raises +Dynamoid::Errors::MissingRangeKey+ if a sort key is
|
549
|
+
# required but has value +nil+.
|
550
|
+
#
|
551
|
+
# There are the following differences between transactional and
|
552
|
+
# non-transactional +#update_attributes!+:
|
553
|
+
# - transactional +#update_attributes!+ doesn't support +lock_version+
|
554
|
+
# attribute so it will not be incremented and will not be checked to detect
|
555
|
+
# concurrent modification of a model and
|
556
|
+
# +Dynamoid::Errors::StaleObjectError+ exception will not be raised
|
557
|
+
# - transactional +update_attributes!+ doesn't raise
|
558
|
+
# +Dynamoid::Errors::StaleObjectError+ when a model that is being updated
|
559
|
+
# was concurrently deleted
|
560
|
+
# - a table isn't created lazily if it doesn't exist yet
|
561
|
+
#
|
390
562
|
# @param model [Dynamoid::Document] a model
|
391
563
|
# @param attributes [Hash] a hash of attributes to update
|
392
564
|
def update_attributes!(model, attributes)
|
@@ -408,7 +580,18 @@ module Dynamoid
|
|
408
580
|
# t.delete(User, user_id)
|
409
581
|
# end
|
410
582
|
#
|
411
|
-
#
|
583
|
+
# Raises +Dynamoid::Errors::MissingHashKey+ if a partition key has value
|
584
|
+
# +nil+ and raises +Dynamoid::Errors::MissingRangeKey+ if a sort key is
|
585
|
+
# required but has value +nil+.
|
586
|
+
#
|
587
|
+
# There are the following differences between transactional and
|
588
|
+
# non-transactional +#delete+: TBD
|
589
|
+
# - transactional +#delete+ doesn't support +lock_version+ attribute so it
|
590
|
+
# will not be incremented and will not be checked to detect concurrent
|
591
|
+
# modification of a model and +Dynamoid::Errors::StaleObjectError+
|
592
|
+
# exception will not be raised
|
593
|
+
# - transactional +#delete+ doesn't disassociate a model from associated ones
|
594
|
+
# if there is any
|
412
595
|
#
|
413
596
|
# @param model_or_model_class [Class|Dynamoid::Document] either model or model class
|
414
597
|
# @param hash_key [Scalar value] hash key value
|
@@ -430,6 +613,19 @@ module Dynamoid
|
|
430
613
|
# Raises +Dynamoid::Errors::RecordNotDestroyed+ exception if model deleting
|
431
614
|
# failed (e.g. aborted by a callback).
|
432
615
|
#
|
616
|
+
# Raises +Dynamoid::Errors::MissingHashKey+ if a partition key has value
|
617
|
+
# +nil+ and raises +Dynamoid::Errors::MissingRangeKey+ if a sort key is
|
618
|
+
# required but has value +nil+.
|
619
|
+
#
|
620
|
+
# There are the following differences between transactional and
|
621
|
+
# non-transactional +#destroy!+:
|
622
|
+
# - transactional +#destroy!+ doesn't support +lock_version+ attribute so it
|
623
|
+
# will not be incremented and will not be checked to detect concurrent
|
624
|
+
# modification of a model and +Dynamoid::Errors::StaleObjectError+
|
625
|
+
# exception will not be raised
|
626
|
+
# - transactional +#destroy!+ doesn't disassociate a model from associated ones
|
627
|
+
# if there are association declared in the model class
|
628
|
+
#
|
433
629
|
# @param model [Dynamoid::Document] a model
|
434
630
|
# @return [Dynamoid::Document|false] returns self if destoying is succefull, +false+ otherwise
|
435
631
|
def destroy!(model)
|
@@ -441,6 +637,19 @@ module Dynamoid
|
|
441
637
|
#
|
442
638
|
# Runs callbacks.
|
443
639
|
#
|
640
|
+
# Raises +Dynamoid::Errors::MissingHashKey+ if a partition key has value
|
641
|
+
# +nil+ and raises +Dynamoid::Errors::MissingRangeKey+ if a sort key is
|
642
|
+
# required but has value +nil+.
|
643
|
+
#
|
644
|
+
# There are the following differences between transactional and
|
645
|
+
# non-transactional +#destroy+:
|
646
|
+
# - transactional +#destroy+ doesn't support +lock_version+ attribute so it
|
647
|
+
# will not be incremented and will not be checked to detect concurrent
|
648
|
+
# modification of a model and +Dynamoid::Errors::StaleObjectError+
|
649
|
+
# exception will not be raised
|
650
|
+
# - transactional +#destroy+ doesn't disassociate a model from associated ones
|
651
|
+
# if there are association declared in the model class
|
652
|
+
#
|
444
653
|
# @param model [Dynamoid::Document] a model
|
445
654
|
# @return [Dynamoid::Document] self
|
446
655
|
def destroy(model)
|
data/lib/dynamoid/validations.rb
CHANGED
@@ -31,17 +31,20 @@ module Dynamoid
|
|
31
31
|
#
|
32
32
|
# @private
|
33
33
|
# @since 0.2.0
|
34
|
-
def save!
|
35
|
-
|
34
|
+
def save!(options = {})
|
35
|
+
unless valid?
|
36
|
+
raise Dynamoid::Errors::DocumentNotValid, self
|
37
|
+
end
|
36
38
|
|
37
|
-
|
38
|
-
self
|
39
|
+
super
|
39
40
|
end
|
40
41
|
|
41
42
|
def update_attribute(attribute, value)
|
42
43
|
write_attribute(attribute, value)
|
43
44
|
save(validate: false)
|
44
45
|
self
|
46
|
+
rescue Dynamoid::Errors::StaleObjectError
|
47
|
+
self
|
45
48
|
end
|
46
49
|
|
47
50
|
module ClassMethods
|
data/lib/dynamoid/version.rb
CHANGED
data/lib/dynamoid.rb
CHANGED
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.
|
4
|
+
version: 3.12.1
|
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: 2025-
|
24
|
+
date: 2025-08-23 00:00:00.000000000 Z
|
25
25
|
dependencies:
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: activemodel
|
@@ -242,12 +242,15 @@ files:
|
|
242
242
|
- lib/dynamoid/tasks.rb
|
243
243
|
- lib/dynamoid/tasks/database.rake
|
244
244
|
- lib/dynamoid/tasks/database.rb
|
245
|
+
- lib/dynamoid/transaction_read.rb
|
246
|
+
- lib/dynamoid/transaction_read/find.rb
|
245
247
|
- lib/dynamoid/transaction_write.rb
|
246
248
|
- lib/dynamoid/transaction_write/base.rb
|
247
249
|
- lib/dynamoid/transaction_write/create.rb
|
248
250
|
- lib/dynamoid/transaction_write/delete_with_instance.rb
|
249
251
|
- lib/dynamoid/transaction_write/delete_with_primary_key.rb
|
250
252
|
- lib/dynamoid/transaction_write/destroy.rb
|
253
|
+
- lib/dynamoid/transaction_write/item_updater.rb
|
251
254
|
- lib/dynamoid/transaction_write/save.rb
|
252
255
|
- lib/dynamoid/transaction_write/update_attributes.rb
|
253
256
|
- lib/dynamoid/transaction_write/update_fields.rb
|
@@ -261,10 +264,10 @@ licenses:
|
|
261
264
|
- MIT
|
262
265
|
metadata:
|
263
266
|
homepage_uri: http://github.com/Dynamoid/dynamoid
|
264
|
-
source_code_uri: https://github.com/Dynamoid/dynamoid/tree/v3.
|
265
|
-
changelog_uri: https://github.com/Dynamoid/dynamoid/blob/v3.
|
267
|
+
source_code_uri: https://github.com/Dynamoid/dynamoid/tree/v3.12.1
|
268
|
+
changelog_uri: https://github.com/Dynamoid/dynamoid/blob/v3.12.1/CHANGELOG.md
|
266
269
|
bug_tracker_uri: https://github.com/Dynamoid/dynamoid/issues
|
267
|
-
documentation_uri: https://www.rubydoc.info/gems/dynamoid/3.
|
270
|
+
documentation_uri: https://www.rubydoc.info/gems/dynamoid/3.12.1
|
268
271
|
funding_uri: https://opencollective.com/dynamoid
|
269
272
|
wiki_uri: https://github.com/Dynamoid/dynamoid/wiki
|
270
273
|
rubygems_mfa_required: 'true'
|