dynamoid 3.3.0 → 3.7.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 (82) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +104 -1
  3. data/README.md +146 -52
  4. data/lib/dynamoid.rb +1 -0
  5. data/lib/dynamoid/adapter.rb +20 -7
  6. data/lib/dynamoid/adapter_plugin/aws_sdk_v3.rb +70 -37
  7. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/batch_get_item.rb +3 -0
  8. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/create_table.rb +20 -12
  9. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/item_updater.rb +5 -4
  10. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/middleware/backoff.rb +2 -2
  11. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/middleware/limit.rb +2 -3
  12. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/middleware/start_key.rb +2 -2
  13. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/query.rb +4 -2
  14. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/scan.rb +4 -2
  15. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/table.rb +1 -0
  16. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/until_past_table_status.rb +2 -1
  17. data/lib/dynamoid/application_time_zone.rb +1 -0
  18. data/lib/dynamoid/associations.rb +182 -19
  19. data/lib/dynamoid/associations/association.rb +10 -2
  20. data/lib/dynamoid/associations/belongs_to.rb +2 -1
  21. data/lib/dynamoid/associations/has_and_belongs_to_many.rb +2 -1
  22. data/lib/dynamoid/associations/has_many.rb +2 -1
  23. data/lib/dynamoid/associations/has_one.rb +2 -1
  24. data/lib/dynamoid/associations/many_association.rb +68 -23
  25. data/lib/dynamoid/associations/single_association.rb +31 -4
  26. data/lib/dynamoid/components.rb +2 -0
  27. data/lib/dynamoid/config.rb +15 -3
  28. data/lib/dynamoid/config/backoff_strategies/constant_backoff.rb +1 -0
  29. data/lib/dynamoid/config/backoff_strategies/exponential_backoff.rb +1 -0
  30. data/lib/dynamoid/config/options.rb +1 -0
  31. data/lib/dynamoid/criteria.rb +9 -1
  32. data/lib/dynamoid/criteria/chain.rb +421 -46
  33. data/lib/dynamoid/criteria/ignored_conditions_detector.rb +3 -3
  34. data/lib/dynamoid/criteria/key_fields_detector.rb +31 -10
  35. data/lib/dynamoid/criteria/nonexistent_fields_detector.rb +3 -2
  36. data/lib/dynamoid/criteria/overwritten_conditions_detector.rb +1 -1
  37. data/lib/dynamoid/dirty.rb +119 -64
  38. data/lib/dynamoid/document.rb +133 -46
  39. data/lib/dynamoid/dumping.rb +9 -0
  40. data/lib/dynamoid/dynamodb_time_zone.rb +1 -0
  41. data/lib/dynamoid/errors.rb +2 -0
  42. data/lib/dynamoid/fields.rb +251 -39
  43. data/lib/dynamoid/fields/declare.rb +86 -0
  44. data/lib/dynamoid/finders.rb +69 -32
  45. data/lib/dynamoid/identity_map.rb +6 -0
  46. data/lib/dynamoid/indexes.rb +86 -17
  47. data/lib/dynamoid/loadable.rb +2 -2
  48. data/lib/dynamoid/log/formatter.rb +26 -0
  49. data/lib/dynamoid/middleware/identity_map.rb +1 -0
  50. data/lib/dynamoid/persistence.rb +502 -104
  51. data/lib/dynamoid/persistence/import.rb +2 -1
  52. data/lib/dynamoid/persistence/save.rb +1 -0
  53. data/lib/dynamoid/persistence/update_fields.rb +5 -2
  54. data/lib/dynamoid/persistence/update_validations.rb +18 -0
  55. data/lib/dynamoid/persistence/upsert.rb +5 -3
  56. data/lib/dynamoid/primary_key_type_mapping.rb +1 -0
  57. data/lib/dynamoid/railtie.rb +1 -0
  58. data/lib/dynamoid/tasks.rb +3 -1
  59. data/lib/dynamoid/tasks/database.rb +1 -0
  60. data/lib/dynamoid/type_casting.rb +12 -2
  61. data/lib/dynamoid/undumping.rb +8 -0
  62. data/lib/dynamoid/validations.rb +6 -1
  63. data/lib/dynamoid/version.rb +1 -1
  64. metadata +48 -75
  65. data/.coveralls.yml +0 -1
  66. data/.document +0 -5
  67. data/.gitignore +0 -74
  68. data/.rspec +0 -2
  69. data/.rubocop.yml +0 -71
  70. data/.rubocop_todo.yml +0 -55
  71. data/.travis.yml +0 -44
  72. data/Appraisals +0 -22
  73. data/Gemfile +0 -8
  74. data/Rakefile +0 -46
  75. data/Vagrantfile +0 -29
  76. data/docker-compose.yml +0 -7
  77. data/dynamoid.gemspec +0 -57
  78. data/gemfiles/rails_4_2.gemfile +0 -9
  79. data/gemfiles/rails_5_0.gemfile +0 -8
  80. data/gemfiles/rails_5_1.gemfile +0 -8
  81. data/gemfiles/rails_5_2.gemfile +0 -8
  82. data/gemfiles/rails_6_0.gemfile +0 -8
@@ -4,6 +4,7 @@ require 'securerandom'
4
4
 
5
5
  module Dynamoid
6
6
  module Persistence
7
+ # @private
7
8
  class Import
8
9
  def self.call(model_class, array_of_attributes)
9
10
  new(model_class, array_of_attributes).call
@@ -32,7 +33,7 @@ module Dynamoid
32
33
  def build_model(attributes)
33
34
  attrs = attributes.symbolize_keys
34
35
 
35
- if Dynamoid::Config.timestamps
36
+ if @model_class.timestamps_enabled?
36
37
  time_now = DateTime.now.in_time_zone(Time.zone)
37
38
  attrs[:created_at] ||= time_now
38
39
  attrs[:updated_at] ||= time_now
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Dynamoid
4
4
  module Persistence
5
+ # @private
5
6
  class Save
6
7
  def self.call(model)
7
8
  new(model).call
@@ -2,9 +2,10 @@
2
2
 
3
3
  module Dynamoid
4
4
  module Persistence
5
+ # @private
5
6
  class UpdateFields
6
- def self.call(*args)
7
- new(*args).call
7
+ def self.call(*args, **options)
8
+ new(*args, **options).call
8
9
  end
9
10
 
10
11
  def initialize(model_class, partition_key:, sort_key:, attributes:, conditions:)
@@ -16,6 +17,8 @@ module Dynamoid
16
17
  end
17
18
 
18
19
  def call
20
+ UpdateValidations.validate_attributes_exist(@model_class, @attributes)
21
+
19
22
  if Dynamoid::Config.timestamps
20
23
  @attributes[:updated_at] ||= DateTime.now.in_time_zone(Time.zone)
21
24
  end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dynamoid
4
+ module Persistence
5
+ # @private
6
+ module UpdateValidations
7
+ def self.validate_attributes_exist(model_class, attributes)
8
+ model_attributes = model_class.attributes.keys
9
+
10
+ attributes.each do |attr_name, _|
11
+ unless model_attributes.include?(attr_name)
12
+ raise Dynamoid::Errors::UnknownAttribute.new("Attribute #{attr_name} does not exist in #{model_class}")
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -2,9 +2,10 @@
2
2
 
3
3
  module Dynamoid
4
4
  module Persistence
5
+ # @private
5
6
  class Upsert
6
- def self.call(*args)
7
- new(*args).call
7
+ def self.call(*args, **options)
8
+ new(*args, **options).call
8
9
  end
9
10
 
10
11
  def initialize(model_class, partition_key:, sort_key:, attributes:, conditions:)
@@ -16,6 +17,8 @@ module Dynamoid
16
17
  end
17
18
 
18
19
  def call
20
+ UpdateValidations.validate_attributes_exist(@model_class, @attributes)
21
+
19
22
  if Dynamoid::Config.timestamps
20
23
  @attributes[:updated_at] ||= DateTime.now.in_time_zone(Time.zone)
21
24
  end
@@ -57,4 +60,3 @@ module Dynamoid
57
60
  end
58
61
  end
59
62
  end
60
-
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dynamoid
4
+ # @private
4
5
  class PrimaryKeyTypeMapping
5
6
  def self.dynamodb_type(type, options)
6
7
  if type.is_a?(Class)
@@ -3,6 +3,7 @@
3
3
  if defined? Rails
4
4
 
5
5
  module Dynamoid
6
+ # @private
6
7
  class Railtie < Rails::Railtie
7
8
  rake_tasks do
8
9
  Dir[File.join(File.dirname(__FILE__), 'tasks/*.rake')].each { |f| load f }
@@ -1 +1,3 @@
1
- load "dynamoid/tasks/database.rake"
1
+ # frozen_string_literal: true
2
+
3
+ load 'dynamoid/tasks/database.rake'
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dynamoid
4
+ # @private
4
5
  module Tasks
5
6
  module Database
6
7
  module_function
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dynamoid
4
+ # @private
4
5
  module TypeCasting
5
6
  def self.cast_attributes(attributes, attributes_options)
6
7
  {}.tap do |h|
@@ -35,6 +36,7 @@ module Dynamoid
35
36
  when :raw then RawTypeCaster
36
37
  when :serialized then SerializedTypeCaster
37
38
  when :boolean then BooleanTypeCaster
39
+ when :binary then BinaryTypeCaster
38
40
  when Class then CustomTypeCaster
39
41
  end
40
42
 
@@ -215,8 +217,6 @@ module Dynamoid
215
217
  value.to_hash
216
218
  elsif value.respond_to? :to_h
217
219
  value.to_h
218
- else
219
- nil
220
220
  end
221
221
  end
222
222
  end
@@ -285,6 +285,16 @@ module Dynamoid
285
285
  end
286
286
  end
287
287
 
288
+ class BinaryTypeCaster < Base
289
+ def process(value)
290
+ if value.is_a? String
291
+ value.dup
292
+ else
293
+ value.to_s
294
+ end
295
+ end
296
+ end
297
+
288
298
  class CustomTypeCaster < Base
289
299
  end
290
300
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dynamoid
4
+ # @private
4
5
  module Undumping
5
6
  def self.undump_attributes(attributes, attributes_options)
6
7
  {}.tap do |h|
@@ -38,6 +39,7 @@ module Dynamoid
38
39
  when :raw then RawUndumper
39
40
  when :serialized then SerializedUndumper
40
41
  when :boolean then BooleanUndumper
42
+ when :binary then BinaryUndumper
41
43
  when Class then CustomTypeUndumper
42
44
  end
43
45
 
@@ -262,6 +264,12 @@ module Dynamoid
262
264
  end
263
265
  end
264
266
 
267
+ class BinaryUndumper < Base
268
+ def process(value)
269
+ Base64.strict_decode64(value)
270
+ end
271
+ end
272
+
265
273
  class CustomTypeUndumper < Base
266
274
  def process(value)
267
275
  field_class = @options[:type]
@@ -10,6 +10,7 @@ module Dynamoid
10
10
 
11
11
  # Override save to provide validation support.
12
12
  #
13
+ # @private
13
14
  # @since 0.2.0
14
15
  def save(options = {})
15
16
  options.reverse_merge!(validate: true)
@@ -28,6 +29,7 @@ module Dynamoid
28
29
 
29
30
  # Raise an error unless this object is valid.
30
31
  #
32
+ # @private
31
33
  # @since 0.2.0
32
34
  def save!
33
35
  raise Dynamoid::Errors::DocumentNotValid, self unless valid?
@@ -48,7 +50,10 @@ module Dynamoid
48
50
  class PresenceValidator < ActiveModel::EachValidator
49
51
  # Validate the record for the record and value.
50
52
  def validate_each(record, attr_name, value)
51
- record.errors.add(attr_name, :blank, options) if not_present?(value)
53
+ # Use keyword argument `options` because it was a Hash in Rails < 6.1
54
+ # and became a keyword argument in 6.1. This way it works in both
55
+ # cases.
56
+ record.errors.add(attr_name, :blank, **options) if not_present?(value)
52
57
  end
53
58
 
54
59
  private
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dynamoid
4
- VERSION = '3.3.0'
4
+ VERSION = '3.7.0'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dynamoid
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.3.0
4
+ version: 3.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josh Symonds
@@ -18,10 +18,10 @@ authors:
18
18
  - Brian Glusman
19
19
  - Peter Boling
20
20
  - Andrew Konchin
21
- autorequire:
22
- bindir: exe
21
+ autorequire:
22
+ bindir: bin
23
23
  cert_chain: []
24
- date: 2019-08-20 00:00:00.000000000 Z
24
+ date: 2021-02-02 00:00:00.000000000 Z
25
25
  dependencies:
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: activemodel
@@ -43,14 +43,14 @@ dependencies:
43
43
  requirements:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
- version: '1'
46
+ version: '1.0'
47
47
  type: :runtime
48
48
  prerelease: false
49
49
  version_requirements: !ruby/object:Gem::Requirement
50
50
  requirements:
51
51
  - - "~>"
52
52
  - !ruby/object:Gem::Version
53
- version: '1'
53
+ version: '1.0'
54
54
  - !ruby/object:Gem::Dependency
55
55
  name: concurrent-ruby
56
56
  requirement: !ruby/object:Gem::Requirement
@@ -65,34 +65,20 @@ dependencies:
65
65
  - - ">="
66
66
  - !ruby/object:Gem::Version
67
67
  version: '1.0'
68
- - !ruby/object:Gem::Dependency
69
- name: null-logger
70
- requirement: !ruby/object:Gem::Requirement
71
- requirements:
72
- - - ">="
73
- - !ruby/object:Gem::Version
74
- version: '0'
75
- type: :runtime
76
- prerelease: false
77
- version_requirements: !ruby/object:Gem::Requirement
78
- requirements:
79
- - - ">="
80
- - !ruby/object:Gem::Version
81
- version: '0'
82
68
  - !ruby/object:Gem::Dependency
83
69
  name: appraisal
84
70
  requirement: !ruby/object:Gem::Requirement
85
71
  requirements:
86
- - - ">="
72
+ - - "~>"
87
73
  - !ruby/object:Gem::Version
88
- version: '0'
74
+ version: '2.2'
89
75
  type: :development
90
76
  prerelease: false
91
77
  version_requirements: !ruby/object:Gem::Requirement
92
78
  requirements:
93
- - - ">="
79
+ - - "~>"
94
80
  - !ruby/object:Gem::Version
95
- version: '0'
81
+ version: '2.2'
96
82
  - !ruby/object:Gem::Dependency
97
83
  name: bundler
98
84
  requirement: !ruby/object:Gem::Requirement
@@ -111,58 +97,58 @@ dependencies:
111
97
  name: coveralls
112
98
  requirement: !ruby/object:Gem::Requirement
113
99
  requirements:
114
- - - ">="
100
+ - - "~>"
115
101
  - !ruby/object:Gem::Version
116
- version: '0'
102
+ version: '0.8'
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'
109
+ version: '0.8'
124
110
  - !ruby/object:Gem::Dependency
125
111
  name: pry
126
112
  requirement: !ruby/object:Gem::Requirement
127
113
  requirements:
128
- - - ">="
114
+ - - "~>"
129
115
  - !ruby/object:Gem::Version
130
- version: '0'
116
+ version: 0.12.0
131
117
  type: :development
132
118
  prerelease: false
133
119
  version_requirements: !ruby/object:Gem::Requirement
134
120
  requirements:
135
- - - ">="
121
+ - - "~>"
136
122
  - !ruby/object:Gem::Version
137
- version: '0'
123
+ version: 0.12.0
138
124
  - !ruby/object:Gem::Dependency
139
125
  name: rake
140
126
  requirement: !ruby/object:Gem::Requirement
141
127
  requirements:
142
- - - ">="
128
+ - - "~>"
143
129
  - !ruby/object:Gem::Version
144
- version: '0'
130
+ version: '13.0'
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: '0'
137
+ version: '13.0'
152
138
  - !ruby/object:Gem::Dependency
153
139
  name: rspec
154
140
  requirement: !ruby/object:Gem::Requirement
155
141
  requirements:
156
- - - ">="
142
+ - - "~>"
157
143
  - !ruby/object:Gem::Version
158
- version: '0'
144
+ version: '3.9'
159
145
  type: :development
160
146
  prerelease: false
161
147
  version_requirements: !ruby/object:Gem::Requirement
162
148
  requirements:
163
- - - ">="
149
+ - - "~>"
164
150
  - !ruby/object:Gem::Version
165
- version: '0'
151
+ version: '3.9'
166
152
  - !ruby/object:Gem::Dependency
167
153
  name: rubocop
168
154
  requirement: !ruby/object:Gem::Requirement
@@ -181,63 +167,44 @@ dependencies:
181
167
  name: wwtd
182
168
  requirement: !ruby/object:Gem::Requirement
183
169
  requirements:
184
- - - ">="
170
+ - - "~>"
185
171
  - !ruby/object:Gem::Version
186
- version: '0'
172
+ version: '1.4'
187
173
  type: :development
188
174
  prerelease: false
189
175
  version_requirements: !ruby/object:Gem::Requirement
190
176
  requirements:
191
- - - ">="
177
+ - - "~>"
192
178
  - !ruby/object:Gem::Version
193
- version: '0'
179
+ version: '1.4'
194
180
  - !ruby/object:Gem::Dependency
195
181
  name: yard
196
182
  requirement: !ruby/object:Gem::Requirement
197
183
  requirements:
198
- - - ">="
184
+ - - "~>"
199
185
  - !ruby/object:Gem::Version
200
- version: '0'
186
+ version: '0.9'
201
187
  type: :development
202
188
  prerelease: false
203
189
  version_requirements: !ruby/object:Gem::Requirement
204
190
  requirements:
205
- - - ">="
191
+ - - "~>"
206
192
  - !ruby/object:Gem::Version
207
- version: '0'
193
+ version: '0.9'
208
194
  description: Dynamoid is an ORM for Amazon's DynamoDB that supports offline development,
209
195
  associations, querying, and everything else you'd expect from an ActiveRecord-style
210
196
  replacement.
211
197
  email:
212
198
  - peter.boling@gmail.com
213
199
  - brian@stellaservice.com
200
+ - andry.konchin@gmail.com
214
201
  executables: []
215
202
  extensions: []
216
- extra_rdoc_files:
217
- - LICENSE.txt
218
- - README.md
203
+ extra_rdoc_files: []
219
204
  files:
220
- - ".coveralls.yml"
221
- - ".document"
222
- - ".gitignore"
223
- - ".rspec"
224
- - ".rubocop.yml"
225
- - ".rubocop_todo.yml"
226
- - ".travis.yml"
227
- - Appraisals
228
205
  - CHANGELOG.md
229
- - Gemfile
230
206
  - LICENSE.txt
231
207
  - README.md
232
- - Rakefile
233
- - Vagrantfile
234
- - docker-compose.yml
235
- - dynamoid.gemspec
236
- - gemfiles/rails_4_2.gemfile
237
- - gemfiles/rails_5_0.gemfile
238
- - gemfiles/rails_5_1.gemfile
239
- - gemfiles/rails_5_2.gemfile
240
- - gemfiles/rails_6_0.gemfile
241
208
  - lib/dynamoid.rb
242
209
  - lib/dynamoid/adapter.rb
243
210
  - lib/dynamoid/adapter_plugin/aws_sdk_v3.rb
@@ -277,15 +244,18 @@ files:
277
244
  - lib/dynamoid/dynamodb_time_zone.rb
278
245
  - lib/dynamoid/errors.rb
279
246
  - lib/dynamoid/fields.rb
247
+ - lib/dynamoid/fields/declare.rb
280
248
  - lib/dynamoid/finders.rb
281
249
  - lib/dynamoid/identity_map.rb
282
250
  - lib/dynamoid/indexes.rb
283
251
  - lib/dynamoid/loadable.rb
252
+ - lib/dynamoid/log/formatter.rb
284
253
  - lib/dynamoid/middleware/identity_map.rb
285
254
  - lib/dynamoid/persistence.rb
286
255
  - lib/dynamoid/persistence/import.rb
287
256
  - lib/dynamoid/persistence/save.rb
288
257
  - lib/dynamoid/persistence/update_fields.rb
258
+ - lib/dynamoid/persistence/update_validations.rb
289
259
  - lib/dynamoid/persistence/upsert.rb
290
260
  - lib/dynamoid/primary_key_type_mapping.rb
291
261
  - lib/dynamoid/railtie.rb
@@ -296,11 +266,15 @@ files:
296
266
  - lib/dynamoid/undumping.rb
297
267
  - lib/dynamoid/validations.rb
298
268
  - lib/dynamoid/version.rb
299
- homepage: http://github.com/Dynamoid/Dynamoid
269
+ homepage: http://github.com/Dynamoid/dynamoid
300
270
  licenses:
301
271
  - MIT
302
- metadata: {}
303
- post_install_message:
272
+ metadata:
273
+ bug_tracker_uri: https://github.com/Dynamoid/dynamoid/issues
274
+ changelog_uri: https://github.com/Dynamoid/dynamoid/tree/v3.7.0/CHANGELOG.md
275
+ source_code_uri: https://github.com/Dynamoid/dynamoid/tree/v3.7.0
276
+ documentation_uri: https://rubydoc.info/gems/dynamoid/3.7.0
277
+ post_install_message:
304
278
  rdoc_options: []
305
279
  require_paths:
306
280
  - lib
@@ -315,9 +289,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
315
289
  - !ruby/object:Gem::Version
316
290
  version: '0'
317
291
  requirements: []
318
- rubyforge_project:
319
- rubygems_version: 2.7.6
320
- signing_key:
292
+ rubygems_version: 3.2.0
293
+ signing_key:
321
294
  specification_version: 4
322
295
  summary: Dynamoid is an ORM for Amazon's DynamoDB
323
296
  test_files: []