dynamoid 3.4.0 → 3.7.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +94 -3
- data/README.md +52 -26
- data/lib/dynamoid.rb +1 -0
- data/lib/dynamoid/adapter.rb +15 -6
- data/lib/dynamoid/adapter_plugin/aws_sdk_v3.rb +48 -36
- data/lib/dynamoid/adapter_plugin/aws_sdk_v3/batch_get_item.rb +13 -1
- data/lib/dynamoid/adapter_plugin/aws_sdk_v3/create_table.rb +9 -8
- data/lib/dynamoid/adapter_plugin/aws_sdk_v3/item_updater.rb +5 -4
- data/lib/dynamoid/adapter_plugin/aws_sdk_v3/middleware/backoff.rb +2 -2
- data/lib/dynamoid/adapter_plugin/aws_sdk_v3/middleware/limit.rb +2 -3
- data/lib/dynamoid/adapter_plugin/aws_sdk_v3/middleware/start_key.rb +2 -2
- data/lib/dynamoid/adapter_plugin/aws_sdk_v3/query.rb +4 -2
- data/lib/dynamoid/adapter_plugin/aws_sdk_v3/scan.rb +6 -3
- data/lib/dynamoid/adapter_plugin/aws_sdk_v3/table.rb +1 -0
- data/lib/dynamoid/adapter_plugin/aws_sdk_v3/until_past_table_status.rb +2 -1
- data/lib/dynamoid/application_time_zone.rb +1 -0
- data/lib/dynamoid/associations.rb +182 -19
- data/lib/dynamoid/associations/association.rb +10 -2
- data/lib/dynamoid/associations/belongs_to.rb +2 -1
- data/lib/dynamoid/associations/has_and_belongs_to_many.rb +2 -1
- data/lib/dynamoid/associations/has_many.rb +2 -1
- data/lib/dynamoid/associations/has_one.rb +2 -1
- data/lib/dynamoid/associations/many_association.rb +68 -23
- data/lib/dynamoid/associations/single_association.rb +31 -4
- data/lib/dynamoid/components.rb +1 -0
- data/lib/dynamoid/config.rb +5 -5
- data/lib/dynamoid/config/backoff_strategies/constant_backoff.rb +1 -0
- data/lib/dynamoid/config/backoff_strategies/exponential_backoff.rb +1 -0
- data/lib/dynamoid/config/options.rb +1 -0
- data/lib/dynamoid/criteria.rb +9 -1
- data/lib/dynamoid/criteria/chain.rb +422 -46
- data/lib/dynamoid/criteria/ignored_conditions_detector.rb +3 -3
- data/lib/dynamoid/criteria/key_fields_detector.rb +32 -11
- data/lib/dynamoid/criteria/nonexistent_fields_detector.rb +3 -2
- data/lib/dynamoid/criteria/overwritten_conditions_detector.rb +1 -1
- data/lib/dynamoid/dirty.rb +119 -64
- data/lib/dynamoid/document.rb +125 -43
- data/lib/dynamoid/dumping.rb +9 -0
- data/lib/dynamoid/dynamodb_time_zone.rb +1 -0
- data/lib/dynamoid/errors.rb +2 -0
- data/lib/dynamoid/fields.rb +217 -36
- data/lib/dynamoid/fields/declare.rb +86 -0
- data/lib/dynamoid/finders.rb +69 -32
- data/lib/dynamoid/identity_map.rb +6 -0
- data/lib/dynamoid/indexes.rb +86 -17
- data/lib/dynamoid/loadable.rb +2 -2
- data/lib/dynamoid/log/formatter.rb +26 -0
- data/lib/dynamoid/middleware/identity_map.rb +1 -0
- data/lib/dynamoid/persistence.rb +496 -104
- data/lib/dynamoid/persistence/import.rb +1 -0
- data/lib/dynamoid/persistence/save.rb +1 -0
- data/lib/dynamoid/persistence/update_fields.rb +5 -2
- data/lib/dynamoid/persistence/update_validations.rb +18 -0
- data/lib/dynamoid/persistence/upsert.rb +5 -3
- data/lib/dynamoid/primary_key_type_mapping.rb +1 -0
- data/lib/dynamoid/railtie.rb +1 -0
- data/lib/dynamoid/tasks.rb +3 -1
- data/lib/dynamoid/tasks/database.rb +1 -0
- data/lib/dynamoid/type_casting.rb +12 -2
- data/lib/dynamoid/undumping.rb +8 -0
- data/lib/dynamoid/validations.rb +6 -1
- data/lib/dynamoid/version.rb +1 -1
- metadata +48 -74
- data/.coveralls.yml +0 -1
- data/.document +0 -5
- data/.gitignore +0 -74
- data/.rspec +0 -2
- data/.rubocop.yml +0 -71
- data/.rubocop_todo.yml +0 -55
- data/.travis.yml +0 -44
- data/Appraisals +0 -22
- data/Gemfile +0 -8
- data/Rakefile +0 -46
- data/Vagrantfile +0 -29
- data/docker-compose.yml +0 -7
- data/dynamoid.gemspec +0 -57
- data/gemfiles/rails_4_2.gemfile +0 -9
- data/gemfiles/rails_5_0.gemfile +0 -8
- data/gemfiles/rails_5_1.gemfile +0 -8
- data/gemfiles/rails_5_2.gemfile +0 -8
- data/gemfiles/rails_6_0.gemfile +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bc5c35cc32f9e77598030b980baff43156095b9480be6984d67e2cb5116fae47
|
4
|
+
data.tar.gz: 7b8ff766d64bf83096bf641f7ca641ab15974f451481a215cf63b69597cf4126
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0f4ac62013723a6880583471808d823cdbd4b84944357249a4dbad7b4087cf32bffc53880ec599c2f5fd61b07136ce7f7be05677fdc0aedf80ae3cf3c2b7b0ee
|
7
|
+
data.tar.gz: 3da0f1ffa1225c5233032330d6d1b9c5e2da60979770b42faecbd8141fd8bd5b9520767c2cc01beb5cee8a7979996cdaa53c3a03c49815c3b01dd23c8dabbb37
|
data/CHANGELOG.md
CHANGED
@@ -1,12 +1,103 @@
|
|
1
1
|
# HEAD
|
2
2
|
|
3
|
-
|
3
|
+
---
|
4
|
+
|
5
|
+
|
6
|
+
|
7
|
+
# 3.7.1 / 2021-06-30
|
8
|
+
|
9
|
+
## Fixes
|
10
|
+
|
11
|
+
* [#484](https://github.com/Dynamoid/dynamoid/pull/484) Fix model deletion - update cached foreign keys in associated models when delete a model
|
12
|
+
* [#492](https://github.com/Dynamoid/dynamoid/pull/492) Fix using `:date` field as an index hash/range key (@yoshida-eth0)
|
13
|
+
* [#503](https://github.com/Dynamoid/dynamoid/pull/503) Fix explicit forcing index with `#with_index` method when perform Scan operation (@bmalinconico)
|
14
|
+
* [#511](https://github.com/Dynamoid/dynamoid/pull/511) Fix `BatchGetItem` operation when partial result returned (so there are unprocessed keys) and table has a range key. The fix affects `.find_all` method only (@Bajena)
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
# 3.7.0 / 2021-02-02
|
19
|
+
|
4
20
|
|
5
21
|
## Features
|
6
22
|
|
23
|
+
* [#476](https://github.com/Dynamoid/dynamoid/pull/476) Added `#with_index` method to force an index in query (@bmalinconico)
|
24
|
+
* [#481](https://github.com/Dynamoid/dynamoid/pull/481) Added `alias` option to the `field` method to declare a field alias and use more conventional name to set and get value
|
25
|
+
|
7
26
|
## Improvements
|
8
27
|
|
28
|
+
* [#482](https://github.com/Dynamoid/dynamoid/pull/482) Support Ruby 3.0 and Rails 6.1
|
29
|
+
* [#461](https://github.com/Dynamoid/dynamoid/pull/461) Allow to delete item attribute with `#update` method (@jkirsteins)
|
30
|
+
* [#463](https://github.com/Dynamoid/dynamoid/pull/463) Raise `UnknownAttribute` exception when specified not declared attribute name (@AlexGascon)
|
31
|
+
|
32
|
+
## Fixes
|
33
|
+
|
34
|
+
* [#480](https://github.com/Dynamoid/dynamoid/pull/480) Repair `.consistent`/`.delete_all`/`.destroy_all` calls directly on a model class
|
35
|
+
* [#484](https://github.com/Dynamoid/dynamoid/pull/484) Fix broken foreign keys after model deleting (@kkan)
|
36
|
+
* Fixes in Readme.md: [#470](https://github.com/Dynamoid/dynamoid/pull/470) (@rromanchuk), [#473](https://github.com/Dynamoid/dynamoid/pull/473) (@Rulikkk)
|
37
|
+
|
38
|
+
---
|
39
|
+
|
40
|
+
|
41
|
+
|
42
|
+
# 3.6.0 / 2020-07-13
|
43
|
+
|
44
|
+
|
45
|
+
## Features
|
46
|
+
|
47
|
+
* [#458](https://github.com/Dynamoid/dynamoid/pull/458) Added `binary` field type
|
48
|
+
* [#459](https://github.com/Dynamoid/dynamoid/pull/459) Added `log_formatter` config option and changed default logging format
|
49
|
+
|
50
|
+
## Improvements
|
51
|
+
|
52
|
+
* [#423](https://github.com/Dynamoid/dynamoid/pull/423) Added warning when generated for a field methods override existing ones
|
53
|
+
* [#429](https://github.com/Dynamoid/dynamoid/pull/429) Added `raise_error` option for `find` method
|
54
|
+
* [#440](https://github.com/Dynamoid/dynamoid/pull/440) Optimized performance of `first` method when there are only conditions on key attribute in a query (@mrkamel)
|
55
|
+
* [#445](https://github.com/Dynamoid/dynamoid/pull/445) Support `limit` parameter in `first` method (@mrkamel)
|
56
|
+
* [#450](https://github.com/Dynamoid/dynamoid/pull/450) Got rid of `null-logger` gem to make Dynamoid dependencies license suitable for commercial use (@yakjuly)
|
57
|
+
* [#454](https://github.com/Dynamoid/dynamoid/pull/454) Added block argument to `create`/`create!` methods
|
58
|
+
* [#456](https://github.com/Dynamoid/dynamoid/pull/456) Detect when `find` method requires a range key argument and raise `Dynamoid::Errors::MissingRangeKey` exception if it's missing
|
59
|
+
* YARD documentation:
|
60
|
+
* added missing documentation so now all the public methods are documented
|
61
|
+
* hid all the private methods and classes
|
62
|
+
|
63
|
+
## Fixes
|
64
|
+
|
65
|
+
* [#425](https://github.com/Dynamoid/dynamoid/pull/425) Fixed typos in the README.md file (@omarsotillo)
|
66
|
+
* [#432](https://github.com/Dynamoid/dynamoid/pull/432) Support tables that use "hash_key" as their partition key name (@remomueller)
|
67
|
+
* [#434](https://github.com/Dynamoid/dynamoid/pull/434) Support tables that have attribute with name "range_value"
|
68
|
+
* [#453](https://github.com/Dynamoid/dynamoid/pull/453) Fixed issue with using `type` attribute as a GSI hash key
|
69
|
+
|
70
|
+
---
|
71
|
+
|
72
|
+
|
73
|
+
|
74
|
+
# 3.5.0 / 2020-04-04
|
75
|
+
|
76
|
+
|
77
|
+
## Features
|
78
|
+
* Feature: [#405](https://github.com/Dynamoid/dynamoid/pull/405) Added `update!` class method (@UrsaDK)
|
79
|
+
* Feature: [#408](https://github.com/Dynamoid/dynamoid/pull/408) Added `ActiveSupport` load hook on `Dynamoid` load (@aaronmallen)
|
80
|
+
* Feature: [#422](https://github.com/Dynamoid/dynamoid/pull/422) Added `.pluck` method
|
81
|
+
|
82
|
+
## Fixes:
|
83
|
+
* Fix: [#410](https://github.com/Dynamoid/dynamoid/pull/410) Fixed creating GSI when table uses on-demand capacity provisioning (@icy-arctic-fox)
|
84
|
+
* Fix: [#414](https://github.com/Dynamoid/dynamoid/pull/414) Fixed lazy table creation
|
85
|
+
* Fix: [#415](https://github.com/Dynamoid/dynamoid/pull/415) Fixed RubyDoc comment (@walkersumida)
|
86
|
+
* Fix: [#420](https://github.com/Dynamoid/dynamoid/pull/420) Fixed `#persisted?` for deleted/destroyed models
|
87
|
+
|
88
|
+
## Improvements:
|
89
|
+
* Improvement: [#416](https://github.com/Dynamoid/dynamoid/pull/416) Improved speed of Adapter's `truncate` method. It now uses `#batch_delete_item` method (@TheSmartnik)
|
90
|
+
* Improvement: [#421](https://github.com/Dynamoid/dynamoid/pull/421) Added `touch: false` option of the #save method
|
91
|
+
* Improvement: [#423](https://github.com/Dynamoid/dynamoid/pull/423) Added warning when generated for a field methods override existing ones
|
92
|
+
|
93
|
+
---
|
94
|
+
|
95
|
+
|
96
|
+
|
97
|
+
# 3.4.1
|
98
|
+
|
9
99
|
## Fixes
|
100
|
+
* Fix: [#398](https://github.com/Dynamoid/dynamoid/pull/398) Fix broken configuration
|
10
101
|
|
11
102
|
---
|
12
103
|
|
@@ -28,8 +119,8 @@
|
|
28
119
|
|
29
120
|
## Fixes
|
30
121
|
|
31
|
-
Fix: [#382](https://github.com/Dynamoid/dynamoid/pull/382) Fixed deprecation warning about `Module#parent_name` in Rails 6 (@tmandke)
|
32
|
-
Fix: Typos in Readme.md (@romeuhcf)
|
122
|
+
* Fix: [#382](https://github.com/Dynamoid/dynamoid/pull/382) Fixed deprecation warning about `Module#parent_name` in Rails 6 (@tmandke)
|
123
|
+
* Fix: Typos in Readme.md (@romeuhcf)
|
33
124
|
|
34
125
|
---
|
35
126
|
|
data/README.md
CHANGED
@@ -126,8 +126,8 @@ end
|
|
126
126
|
Dynamoid supports Ruby >= 2.3 and Rails >= 4.2.
|
127
127
|
|
128
128
|
Its compatibility is tested against following Ruby versions: 2.3, 2.4,
|
129
|
-
2.5
|
130
|
-
5.2 and 6.
|
129
|
+
2.5, 2.6, 2.7 and 3.0, JRuby 9.2.x and against Rails versions: 4.2, 5.0, 5.1,
|
130
|
+
5.2, 6.0 and 6.1.
|
131
131
|
|
132
132
|
## Setup
|
133
133
|
|
@@ -212,16 +212,17 @@ each field. Every field on the object must be included here; if you miss
|
|
212
212
|
any they'll be completely bypassed during DynamoDB's initialization and
|
213
213
|
will not appear on the model objects.
|
214
214
|
|
215
|
-
By default, fields are assumed to be of type
|
216
|
-
types are
|
217
|
-
`date`,
|
218
|
-
List and Map DynamoDB types respectively. `raw` type means
|
219
|
-
Ruby Array, Hash, String and numbers. If built-in types do
|
220
|
-
you can use a custom field type represented by an
|
221
|
-
provided that the class supports a compatible
|
222
|
-
The primary use case for using a custom field
|
223
|
-
business logic with high-level types, while
|
224
|
-
backward-compatibility of the serialized
|
215
|
+
By default, fields are assumed to be of type `string`. Other built-in
|
216
|
+
types are `integer`, `number`, `set`, `array`, `map`, `datetime`,
|
217
|
+
`date`, `boolean`, `binary`, `raw` and `serialized`. `array` and
|
218
|
+
`map` match List and Map DynamoDB types respectively. `raw` type means
|
219
|
+
you can store Ruby Array, Hash, String and numbers. If built-in types do
|
220
|
+
not suit you, you can use a custom field type represented by an
|
221
|
+
arbitrary class, provided that the class supports a compatible
|
222
|
+
serialization interface. The primary use case for using a custom field
|
223
|
+
type is to represent your business logic with high-level types, while
|
224
|
+
ensuring portability or backward-compatibility of the serialized
|
225
|
+
representation.
|
225
226
|
|
226
227
|
#### Note on boolean type
|
227
228
|
|
@@ -232,7 +233,7 @@ easily achieve this with `store_as_native_boolean` field option:
|
|
232
233
|
|
233
234
|
```ruby
|
234
235
|
class Document
|
235
|
-
include
|
236
|
+
include Dynamoid::Document
|
236
237
|
|
237
238
|
field :active, :boolean, store_as_native_boolean: false
|
238
239
|
end
|
@@ -246,7 +247,7 @@ strings instead then set `store_as_string` to `true`
|
|
246
247
|
|
247
248
|
```ruby
|
248
249
|
class Document
|
249
|
-
include
|
250
|
+
include Dynamoid::Document
|
250
251
|
|
251
252
|
field :sent_on, :date, store_as_string: true
|
252
253
|
end
|
@@ -261,7 +262,7 @@ as ISO-8601 formatted strings instead then set `store_as_string` to
|
|
261
262
|
|
262
263
|
```ruby
|
263
264
|
class Document
|
264
|
-
include
|
265
|
+
include Dynamoid::Document
|
265
266
|
|
266
267
|
field :sent_at, :datetime, store_as_string: true
|
267
268
|
end
|
@@ -293,7 +294,7 @@ types.
|
|
293
294
|
|
294
295
|
```ruby
|
295
296
|
class Document
|
296
|
-
include
|
297
|
+
include Dynamoid::Document
|
297
298
|
|
298
299
|
field :tags, :set, of: :integer
|
299
300
|
end
|
@@ -305,7 +306,7 @@ elements type:
|
|
305
306
|
|
306
307
|
```ruby
|
307
308
|
class Document
|
308
|
-
include
|
309
|
+
include Dynamoid::Document
|
309
310
|
|
310
311
|
field :values, :set, of: { serialized: { serializer: JSON } }
|
311
312
|
field :dates, :set, of: { date: { store_as_string: true } }
|
@@ -329,7 +330,7 @@ natively, you should specify element type with `of` option:
|
|
329
330
|
|
330
331
|
```ruby
|
331
332
|
class Document
|
332
|
-
include
|
333
|
+
include Dynamoid::Document
|
333
334
|
|
334
335
|
field :dates, :array, of: :date
|
335
336
|
end
|
@@ -364,6 +365,26 @@ field :actions_taken, :integer, default: 0
|
|
364
365
|
field :joined_at, :datetime, default: -> { Time.now }
|
365
366
|
```
|
366
367
|
|
368
|
+
#### Aliases
|
369
|
+
|
370
|
+
It might be helpful to define an alias for already existing field when
|
371
|
+
naming convention used for a table differs from conventions common in
|
372
|
+
Ruby:
|
373
|
+
|
374
|
+
```ruby
|
375
|
+
field firstName, :string, alias: :first_name
|
376
|
+
```
|
377
|
+
|
378
|
+
This way there will be generated
|
379
|
+
setters/getters/`<name>?`/`<name>_before_type_cast` methods for both
|
380
|
+
original field name (`firstName`) and an alias (`first_name`).
|
381
|
+
|
382
|
+
```ruby
|
383
|
+
user = User.new(first_name: 'Michael')
|
384
|
+
user.first_name # => 'Michael'
|
385
|
+
user.firstName # => 'Michael'
|
386
|
+
```
|
387
|
+
|
367
388
|
#### Custom Types
|
368
389
|
|
369
390
|
To use a custom type for a field, suppose you have a `Money` type.
|
@@ -575,7 +596,7 @@ c.my_new_type
|
|
575
596
|
|
576
597
|
### Type casting
|
577
598
|
|
578
|
-
|
599
|
+
Dynamoid supports type casting and tries to do it in the most convenient
|
579
600
|
way. Values for all fields (except custom type) are coerced to declared
|
580
601
|
field types.
|
581
602
|
|
@@ -613,7 +634,7 @@ well.
|
|
613
634
|
|
614
635
|
### Dirty API
|
615
636
|
|
616
|
-
Dynamoid supports Dirty API which
|
637
|
+
Dynamoid supports Dirty API which is equivalent to [Rails 5.2
|
617
638
|
`ActiveModel::Dirty`](https://api.rubyonrails.org/v5.2/classes/ActiveModel/Dirty.html).
|
618
639
|
There is only one limitation - change in place of field isn't detected
|
619
640
|
automatically.
|
@@ -631,7 +652,7 @@ u.email = 'josh@joshsymonds.com'
|
|
631
652
|
u.save
|
632
653
|
```
|
633
654
|
|
634
|
-
Save forces persistence to the
|
655
|
+
Save forces persistence to the data store: a unique ID is also assigned,
|
635
656
|
but it is a string and not an auto-incrementing number.
|
636
657
|
|
637
658
|
```ruby
|
@@ -762,7 +783,7 @@ for requesting documents in batches:
|
|
762
783
|
|
763
784
|
```ruby
|
764
785
|
# Do some maintenance on the entire table without flooding DynamoDB
|
765
|
-
Address.
|
786
|
+
Address.batch(100).each { |address| address.do_some_work; sleep(0.01) }
|
766
787
|
Address.record_limit(10_000).batch(100).each { … } # Batch specified as part of a chain
|
767
788
|
```
|
768
789
|
|
@@ -1068,7 +1089,7 @@ Listed below are all configuration options.
|
|
1068
1089
|
* `models_dir` - `dynamoid:create_tables` rake task loads DynamoDb
|
1069
1090
|
models from this directory. Default is `./app/models`.
|
1070
1091
|
* `application_timezone` - Dynamoid converts all `datetime` fields to
|
1071
|
-
|
1092
|
+
specified time zone when loads data from the storage.
|
1072
1093
|
Acceptable values - `:utc`, `:local` (to use system time zone) and
|
1073
1094
|
time zone name e.g. `Eastern Time (US & Canada)`. Default is `utc`
|
1074
1095
|
* `dynamodb_timezone` - When a datetime field is stored in string format
|
@@ -1088,6 +1109,11 @@ Listed below are all configuration options.
|
|
1088
1109
|
`nil`
|
1089
1110
|
* `backoff_strategies`: is a hash and contains all available strategies.
|
1090
1111
|
Default is { constant: ..., exponential: ...}
|
1112
|
+
* `log_formatter`: overrides default AWS SDK formatter. There are
|
1113
|
+
several canned formatters: `Aws::Log::Formatter.default`,
|
1114
|
+
`Aws::Log::Formatter.colored` and `Aws::Log::Formatter.short`. Please
|
1115
|
+
look into `Aws::Log::Formatter` AWS SDK documentation in order to
|
1116
|
+
provide own formatter.
|
1091
1117
|
* `http_continue_timeout`: The number of seconds to wait for a
|
1092
1118
|
100-continue HTTP response before sending the request body. Default
|
1093
1119
|
option value is `nil`. If not specified effected value is `1`
|
@@ -1261,7 +1287,7 @@ class User
|
|
1261
1287
|
end
|
1262
1288
|
|
1263
1289
|
Dynamoid.config.logger.level = :debug
|
1264
|
-
Dynamoid.config.endpoint = 'localhost:8000'
|
1290
|
+
Dynamoid.config.endpoint = 'http://localhost:8000'
|
1265
1291
|
|
1266
1292
|
User.create(name: 'Alex')
|
1267
1293
|
|
@@ -1336,12 +1362,12 @@ environment.
|
|
1336
1362
|
|
1337
1363
|
If you want to run all the specs that travis runs, use `bundle exec
|
1338
1364
|
wwtd`, but first you will need to setup all the rubies, for each of `%w(
|
1339
|
-
2.
|
1365
|
+
2.3.8 2.4.6 2.5.5 2.6.3 2.7.0 3.0.0 9.2.14.0)`. When you run
|
1340
1366
|
`bundle exec wwtd` it will take care of starting and stopping the local
|
1341
1367
|
dynamodb instance.
|
1342
1368
|
|
1343
1369
|
```shell
|
1344
|
-
rvm use
|
1370
|
+
rvm use 3.0.0
|
1345
1371
|
gem install rubygems-update
|
1346
1372
|
gem install bundler
|
1347
1373
|
bundle install
|
data/lib/dynamoid.rb
CHANGED
data/lib/dynamoid/adapter.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
# require only 'concurrent/atom' once this issue is resolved:
|
4
4
|
# https://github.com/ruby-concurrency/concurrent-ruby/pull/377
|
5
5
|
require 'concurrent'
|
6
|
-
require
|
6
|
+
require 'dynamoid/adapter_plugin/aws_sdk_v3'
|
7
7
|
|
8
8
|
# encoding: utf-8
|
9
9
|
module Dynamoid
|
@@ -11,6 +11,7 @@ module Dynamoid
|
|
11
11
|
# 1) For the rest of Dynamoid, the gateway to DynamoDB.
|
12
12
|
# 2) Allows switching `config.adapter` to ease development of a new adapter.
|
13
13
|
# 3) Caches the list of tables Dynamoid knows about.
|
14
|
+
# @private
|
14
15
|
class Adapter
|
15
16
|
def initialize
|
16
17
|
@adapter_ = Concurrent::Atom.new(nil)
|
@@ -78,8 +79,8 @@ module Dynamoid
|
|
78
79
|
#
|
79
80
|
# @param [String] table the name of the table to write the object to
|
80
81
|
# @param [Array] ids to fetch, can also be a string of just one id
|
81
|
-
# @param [Hash] options
|
82
|
-
#
|
82
|
+
# @param [Hash] options Passed to the underlying query. The :range_key option is required whenever the table has a range key,
|
83
|
+
# unless multiple ids are passed in.
|
83
84
|
#
|
84
85
|
# @since 0.2.0
|
85
86
|
def read(table, ids, options = {}, &blk)
|
@@ -94,7 +95,9 @@ module Dynamoid
|
|
94
95
|
#
|
95
96
|
# @param [String] table the name of the table to write the object to
|
96
97
|
# @param [Array] ids to delete, can also be a string of just one id
|
97
|
-
# @param [
|
98
|
+
# @param [Hash] options allowed only +range_key+ - range key or array of
|
99
|
+
# range keys of the record to delete, can also be
|
100
|
+
# a string of just one range_key, and +conditions+
|
98
101
|
#
|
99
102
|
def delete(table, ids, options = {})
|
100
103
|
range_key = options[:range_key] # array of range keys that matches the ids passed in
|
@@ -115,7 +118,7 @@ module Dynamoid
|
|
115
118
|
# Scans a table. Generally quite slow; try to avoid using scan if at all possible.
|
116
119
|
#
|
117
120
|
# @param [String] table the name of the table to write the object to
|
118
|
-
# @param [Hash]
|
121
|
+
# @param [Hash] query a hash of attributes: matching records will be returned by the scan
|
119
122
|
#
|
120
123
|
# @since 0.2.0
|
121
124
|
def scan(table, query = {}, opts = {})
|
@@ -155,8 +158,14 @@ module Dynamoid
|
|
155
158
|
#
|
156
159
|
# @since 0.2.0
|
157
160
|
def method_missing(method, *args, &block)
|
158
|
-
|
161
|
+
# Don't use keywork arguments delegating (with **kw). It works in
|
162
|
+
# different way in different Ruby versions: <= 2.6, 2.7, 3.0 and in some
|
163
|
+
# future 3.x versions. Providing that there are no downstream methods
|
164
|
+
# with keyword arguments in adapter.
|
165
|
+
#
|
166
|
+
# https://eregon.me/blog/2019/11/10/the-delegation-challenge-of-ruby27.html
|
159
167
|
|
168
|
+
return benchmark(method, *args) { adapter.send(method, *args, &block) } if adapter.respond_to?(method)
|
160
169
|
super
|
161
170
|
end
|
162
171
|
|
@@ -9,8 +9,18 @@ require_relative 'aws_sdk_v3/table'
|
|
9
9
|
require_relative 'aws_sdk_v3/until_past_table_status'
|
10
10
|
|
11
11
|
module Dynamoid
|
12
|
+
# @private
|
12
13
|
module AdapterPlugin
|
13
14
|
# The AwsSdkV3 adapter provides support for the aws-sdk version 2 for ruby.
|
15
|
+
|
16
|
+
# Note: Don't use keyword arguments in public methods as far as method
|
17
|
+
# calls on adapter are delegated to the plugin.
|
18
|
+
#
|
19
|
+
# There are breaking changes in Ruby related to delegating keyword
|
20
|
+
# arguments so we have decided just to avoid them when use delegation.
|
21
|
+
#
|
22
|
+
# https://eregon.me/blog/2019/11/10/the-delegation-challenge-of-ruby27.html
|
23
|
+
|
14
24
|
class AwsSdkV3
|
15
25
|
EQ = 'EQ'
|
16
26
|
RANGE_MAP = {
|
@@ -61,6 +71,25 @@ module Dynamoid
|
|
61
71
|
|
62
72
|
attr_reader :table_cache
|
63
73
|
|
74
|
+
# Build an array of values for Condition
|
75
|
+
# Is used in ScanFilter and QueryFilter
|
76
|
+
# https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Condition.html
|
77
|
+
# @param [String] operator value of RANGE_MAP or FIELD_MAP hash, e.g. "EQ", "LT" etc
|
78
|
+
# @param [Object] value scalar value or array/set
|
79
|
+
def self.attribute_value_list(operator, value)
|
80
|
+
# For BETWEEN and IN operators we should keep value as is (it should be already an array)
|
81
|
+
# NULL and NOT_NULL require absence of attribute list
|
82
|
+
# For all the other operators we wrap the value with array
|
83
|
+
# https://docs.aws.amazon.com/en_us/amazondynamodb/latest/developerguide/LegacyConditionalParameters.Conditions.html
|
84
|
+
if %w[BETWEEN IN].include?(operator)
|
85
|
+
[value].flatten
|
86
|
+
elsif %w[NULL NOT_NULL].include?(operator)
|
87
|
+
nil
|
88
|
+
else
|
89
|
+
[value]
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
64
93
|
# Establish the connection to DynamoDB.
|
65
94
|
#
|
66
95
|
# @return [Aws::DynamoDB::Client] the DynamoDB connection
|
@@ -78,23 +107,25 @@ module Dynamoid
|
|
78
107
|
|
79
108
|
# if credentials are passed, they already contain access key & secret key
|
80
109
|
if Dynamoid::Config.credentials?
|
81
|
-
connection_hash[:credentials] = Dynamoid::Config.credentials
|
110
|
+
@connection_hash[:credentials] = Dynamoid::Config.credentials
|
82
111
|
else
|
83
112
|
# otherwise, pass access key & secret key for credentials creation
|
84
113
|
if Dynamoid::Config.access_key?
|
85
|
-
connection_hash[:access_key_id] = Dynamoid::Config.access_key
|
114
|
+
@connection_hash[:access_key_id] = Dynamoid::Config.access_key
|
86
115
|
end
|
87
116
|
if Dynamoid::Config.secret_key?
|
88
|
-
connection_hash[:secret_access_key] = Dynamoid::Config.secret_key
|
117
|
+
@connection_hash[:secret_access_key] = Dynamoid::Config.secret_key
|
89
118
|
end
|
90
119
|
end
|
91
120
|
|
92
|
-
# https://github.com/aws/aws-sdk-ruby/blob/master/gems/aws-sdk-core/lib/aws-sdk-core/plugins/logging.rb
|
93
|
-
# https://github.com/aws/aws-sdk-ruby/blob/master/gems/aws-sdk-core/lib/aws-sdk-core/log/formatter.rb
|
94
|
-
formatter = Aws::Log::Formatter.new(':operation | Request :http_request_body | Response :http_response_body')
|
95
121
|
@connection_hash[:logger] = Dynamoid::Config.logger
|
96
122
|
@connection_hash[:log_level] = :debug
|
97
|
-
|
123
|
+
|
124
|
+
# https://github.com/aws/aws-sdk-ruby/blob/master/gems/aws-sdk-core/lib/aws-sdk-core/plugins/logging.rb
|
125
|
+
# https://github.com/aws/aws-sdk-ruby/blob/master/gems/aws-sdk-core/lib/aws-sdk-core/log/formatter.rb
|
126
|
+
if Dynamoid::Config.log_formatter
|
127
|
+
@connection_hash[:log_formatter] = Dynamoid::Config.log_formatter
|
128
|
+
end
|
98
129
|
|
99
130
|
@connection_hash
|
100
131
|
end
|
@@ -122,9 +153,9 @@ module Dynamoid
|
|
122
153
|
# end
|
123
154
|
#
|
124
155
|
# @param [String] table_name the name of the table
|
125
|
-
# @param [Array]
|
126
|
-
# @param [Hash] additional options
|
127
|
-
# @
|
156
|
+
# @param [Array] objects to be processed
|
157
|
+
# @param [Hash] options additional options
|
158
|
+
# @yield [true|false] invokes an optional block with argument - whether there are unprocessed items
|
128
159
|
#
|
129
160
|
# See:
|
130
161
|
# * http://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_BatchWriteItem.html
|
@@ -179,9 +210,9 @@ module Dynamoid
|
|
179
210
|
# end
|
180
211
|
# end
|
181
212
|
#
|
182
|
-
# @param [Hash]
|
213
|
+
# @param [Hash] table_names_with_ids the hash of tables and IDs to retrieve
|
183
214
|
# @param [Hash] options to be passed to underlying BatchGet call
|
184
|
-
# @param [Proc] optional block can be passed to handle each batch of items
|
215
|
+
# @param [Proc] block optional block can be passed to handle each batch of items
|
185
216
|
#
|
186
217
|
# @return [Hash] a hash where keys are the table names and the values are the retrieved items
|
187
218
|
#
|
@@ -259,7 +290,7 @@ module Dynamoid
|
|
259
290
|
false
|
260
291
|
end
|
261
292
|
|
262
|
-
def update_time_to_live(table_name
|
293
|
+
def update_time_to_live(table_name, attribute)
|
263
294
|
request = {
|
264
295
|
table_name: table_name,
|
265
296
|
time_to_live_specification: {
|
@@ -525,11 +556,11 @@ module Dynamoid
|
|
525
556
|
hk = table.hash_key
|
526
557
|
rk = table.range_key
|
527
558
|
|
528
|
-
scan(table_name, {}, {}).flat_map{ |i| i }.
|
529
|
-
|
530
|
-
opts[:range_key] = attributes[rk.to_sym] if rk
|
531
|
-
delete_item(table_name, attributes[hk], opts)
|
559
|
+
ids = scan(table_name, {}, {}).flat_map { |i| i }.map do |attributes|
|
560
|
+
rk ? [attributes[hk], attributes[rk.to_sym]] : attributes[hk]
|
532
561
|
end
|
562
|
+
|
563
|
+
batch_delete_item(table_name => ids)
|
533
564
|
end
|
534
565
|
|
535
566
|
def count(table_name)
|
@@ -587,25 +618,6 @@ module Dynamoid
|
|
587
618
|
end
|
588
619
|
end
|
589
620
|
|
590
|
-
# Build an array of values for Condition
|
591
|
-
# Is used in ScanFilter and QueryFilter
|
592
|
-
# https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Condition.html
|
593
|
-
# @params [String] operator: value of RANGE_MAP or FIELD_MAP hash, e.g. "EQ", "LT" etc
|
594
|
-
# @params [Object] value: scalar value or array/set
|
595
|
-
def self.attribute_value_list(operator, value)
|
596
|
-
# For BETWEEN and IN operators we should keep value as is (it should be already an array)
|
597
|
-
# NULL and NOT_NULL require absence of attribute list
|
598
|
-
# For all the other operators we wrap the value with array
|
599
|
-
# https://docs.aws.amazon.com/en_us/amazondynamodb/latest/developerguide/LegacyConditionalParameters.Conditions.html
|
600
|
-
if %w[BETWEEN IN].include?(operator)
|
601
|
-
[value].flatten
|
602
|
-
elsif %w[NULL NOT_NULL].include?(operator)
|
603
|
-
nil
|
604
|
-
else
|
605
|
-
[value]
|
606
|
-
end
|
607
|
-
end
|
608
|
-
|
609
621
|
def sanitize_item(attributes)
|
610
622
|
config_value = Dynamoid.config.store_attribute_with_nil_value
|
611
623
|
store_attribute_with_nil_value = config_value.nil? ? false : !!config_value
|