dynamoid 3.1.0 → 3.2.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.
- checksums.yaml +5 -5
- data/.rubocop.yml +18 -0
- data/.travis.yml +5 -3
- data/CHANGELOG.md +15 -0
- data/README.md +113 -63
- data/Vagrantfile +2 -2
- data/docker-compose.yml +1 -1
- data/gemfiles/rails_4_2.gemfile +1 -1
- data/gemfiles/rails_5_0.gemfile +1 -1
- data/gemfiles/rails_5_1.gemfile +1 -1
- data/gemfiles/rails_5_2.gemfile +1 -1
- data/lib/dynamoid/adapter.rb +1 -0
- data/lib/dynamoid/adapter_plugin/aws_sdk_v3.rb +26 -395
- data/lib/dynamoid/adapter_plugin/aws_sdk_v3/create_table.rb +234 -0
- data/lib/dynamoid/adapter_plugin/aws_sdk_v3/item_updater.rb +89 -0
- data/lib/dynamoid/adapter_plugin/aws_sdk_v3/middleware/backoff.rb +24 -0
- data/lib/dynamoid/adapter_plugin/aws_sdk_v3/middleware/limit.rb +57 -0
- data/lib/dynamoid/adapter_plugin/aws_sdk_v3/middleware/start_key.rb +28 -0
- data/lib/dynamoid/adapter_plugin/aws_sdk_v3/query.rb +123 -0
- data/lib/dynamoid/adapter_plugin/aws_sdk_v3/scan.rb +85 -0
- data/lib/dynamoid/adapter_plugin/aws_sdk_v3/table.rb +52 -0
- data/lib/dynamoid/adapter_plugin/aws_sdk_v3/until_past_table_status.rb +60 -0
- data/lib/dynamoid/associations/has_and_belongs_to_many.rb +1 -0
- data/lib/dynamoid/associations/has_many.rb +1 -0
- data/lib/dynamoid/associations/has_one.rb +1 -0
- data/lib/dynamoid/associations/single_association.rb +1 -0
- data/lib/dynamoid/criteria.rb +4 -4
- data/lib/dynamoid/criteria/chain.rb +86 -79
- data/lib/dynamoid/criteria/ignored_conditions_detector.rb +41 -0
- data/lib/dynamoid/criteria/key_fields_detector.rb +61 -0
- data/lib/dynamoid/criteria/nonexistent_fields_detector.rb +41 -0
- data/lib/dynamoid/criteria/overwritten_conditions_detector.rb +40 -0
- data/lib/dynamoid/document.rb +18 -13
- data/lib/dynamoid/dumping.rb +52 -40
- data/lib/dynamoid/fields.rb +4 -3
- data/lib/dynamoid/finders.rb +3 -3
- data/lib/dynamoid/persistence.rb +5 -6
- data/lib/dynamoid/primary_key_type_mapping.rb +1 -1
- data/lib/dynamoid/tasks.rb +1 -0
- data/lib/dynamoid/tasks/database.rake +2 -2
- data/lib/dynamoid/type_casting.rb +37 -19
- data/lib/dynamoid/undumping.rb +53 -42
- data/lib/dynamoid/validations.rb +2 -0
- data/lib/dynamoid/version.rb +1 -1
- metadata +17 -5
- data/lib/dynamoid/adapter_plugin/query.rb +0 -144
- data/lib/dynamoid/adapter_plugin/scan.rb +0 -107
data/lib/dynamoid/finders.rb
CHANGED
@@ -183,7 +183,7 @@ module Dynamoid
|
|
183
183
|
def find_all_by_composite_key(hash_key, options = {})
|
184
184
|
ActiveSupport::Deprecation.warn('[Dynamoid] .find_all_composite_key is deprecated! Call .where instead of')
|
185
185
|
|
186
|
-
Dynamoid.adapter.query(table_name, options.merge(hash_value: hash_key)).collect do |item|
|
186
|
+
Dynamoid.adapter.query(table_name, options.merge(hash_value: hash_key)).flat_map{ |i| i }.collect do |item|
|
187
187
|
from_database(item)
|
188
188
|
end
|
189
189
|
end
|
@@ -240,7 +240,7 @@ module Dynamoid
|
|
240
240
|
opts[range_op_mapped] = range_key_value
|
241
241
|
end
|
242
242
|
dynamo_options = opts.merge(options.reject { |key, _| key == :range })
|
243
|
-
Dynamoid.adapter.query(table_name, dynamo_options).map do |item|
|
243
|
+
Dynamoid.adapter.query(table_name, dynamo_options).flat_map{ |i| i }.map do |item|
|
244
244
|
from_database(item)
|
245
245
|
end
|
246
246
|
end
|
@@ -264,7 +264,7 @@ module Dynamoid
|
|
264
264
|
attributes = method.to_s.split('_by_').last.split('_and_')
|
265
265
|
|
266
266
|
chain = Dynamoid::Criteria::Chain.new(self)
|
267
|
-
chain
|
267
|
+
chain = chain.where({}.tap { |h| attributes.each_with_index { |attr, index| h[attr.to_sym] = args[index] } })
|
268
268
|
|
269
269
|
if finder =~ /all/
|
270
270
|
return chain.all
|
data/lib/dynamoid/persistence.rb
CHANGED
@@ -18,8 +18,7 @@ module Dynamoid
|
|
18
18
|
|
19
19
|
module ClassMethods
|
20
20
|
def table_name
|
21
|
-
table_base_name = options[:name] || base_class.name.split('::').last
|
22
|
-
.downcase.pluralize
|
21
|
+
table_base_name = options[:name] || base_class.name.split('::').last.downcase.pluralize
|
23
22
|
|
24
23
|
@table_name ||= [Dynamoid::Config.namespace.to_s, table_base_name].reject(&:empty?).join('_')
|
25
24
|
end
|
@@ -151,22 +150,22 @@ module Dynamoid
|
|
151
150
|
end
|
152
151
|
end
|
153
152
|
|
154
|
-
# Updates multiple
|
153
|
+
# Updates multiple attributes at once, saving the object once the updates are complete.
|
155
154
|
#
|
156
155
|
# @param [Hash] attributes a hash of attributes to update
|
157
156
|
#
|
158
157
|
# @since 0.2.0
|
159
158
|
def update_attributes(attributes)
|
160
|
-
attributes.each { |attribute, value| write_attribute(attribute, value) }
|
159
|
+
attributes.each { |attribute, value| write_attribute(attribute, value) }
|
161
160
|
save
|
162
161
|
end
|
163
162
|
|
164
|
-
# Updates multiple
|
163
|
+
# Updates multiple attributes at once, saving the object once the updates are complete.
|
165
164
|
# Raises a Dynamoid::Errors::DocumentNotValid exception if there is vaidation and it fails.
|
166
165
|
#
|
167
166
|
# @param [Hash] attributes a hash of attributes to update
|
168
167
|
def update_attributes!(attributes)
|
169
|
-
attributes.each { |attribute, value| write_attribute(attribute, value) }
|
168
|
+
attributes.each { |attribute, value| write_attribute(attribute, value) }
|
170
169
|
save!
|
171
170
|
end
|
172
171
|
|
@@ -0,0 +1 @@
|
|
1
|
+
load "dynamoid/tasks/database.rake"
|
@@ -30,12 +30,12 @@ namespace :dynamoid do
|
|
30
30
|
end
|
31
31
|
|
32
32
|
msg = "Connection to DynamoDB #{success ? 'OK' : 'FAILED'}"
|
33
|
-
msg
|
33
|
+
msg += if Dynamoid.config.endpoint
|
34
34
|
" at local endpoint '#{Dynamoid.config.endpoint}'"
|
35
35
|
else
|
36
36
|
' at remote AWS endpoint'
|
37
37
|
end
|
38
|
-
msg
|
38
|
+
msg += ", reason being '#{failure_reason}'" unless success
|
39
39
|
puts msg
|
40
40
|
end
|
41
41
|
end
|
@@ -29,6 +29,7 @@ module Dynamoid
|
|
29
29
|
when :number then NumberTypeCaster
|
30
30
|
when :set then SetTypeCaster
|
31
31
|
when :array then ArrayTypeCaster
|
32
|
+
when :map then MapTypeCaster
|
32
33
|
when :datetime then DateTimeTypeCaster
|
33
34
|
when :date then DateTypeCaster
|
34
35
|
when :raw then RawTypeCaster
|
@@ -96,7 +97,7 @@ module Dynamoid
|
|
96
97
|
nil
|
97
98
|
elsif value.is_a?(Float) && !value.finite?
|
98
99
|
nil
|
99
|
-
elsif !
|
100
|
+
elsif !value.respond_to?(:to_d)
|
100
101
|
nil
|
101
102
|
else
|
102
103
|
value.to_d
|
@@ -122,8 +123,6 @@ module Dynamoid
|
|
122
123
|
value.dup
|
123
124
|
elsif value.respond_to?(:to_set)
|
124
125
|
value.to_set
|
125
|
-
else
|
126
|
-
nil
|
127
126
|
end
|
128
127
|
end
|
129
128
|
|
@@ -138,20 +137,20 @@ module Dynamoid
|
|
138
137
|
end
|
139
138
|
|
140
139
|
def element_type
|
141
|
-
|
142
|
-
@options[:of]
|
143
|
-
else
|
140
|
+
if @options[:of].is_a?(Hash)
|
144
141
|
@options[:of].keys.first
|
142
|
+
else
|
143
|
+
@options[:of]
|
145
144
|
end
|
146
145
|
end
|
147
146
|
|
148
147
|
def element_options
|
149
|
-
|
150
|
-
{ type: element_type }
|
151
|
-
else
|
148
|
+
if @options[:of].is_a?(Hash)
|
152
149
|
@options[:of][element_type].dup.tap do |options|
|
153
150
|
options[:type] = element_type
|
154
151
|
end
|
152
|
+
else
|
153
|
+
{ type: element_type }
|
155
154
|
end
|
156
155
|
end
|
157
156
|
end
|
@@ -174,8 +173,6 @@ module Dynamoid
|
|
174
173
|
value.dup
|
175
174
|
elsif value.respond_to?(:to_a)
|
176
175
|
value.to_a
|
177
|
-
else
|
178
|
-
nil
|
179
176
|
end
|
180
177
|
end
|
181
178
|
|
@@ -190,20 +187,36 @@ module Dynamoid
|
|
190
187
|
end
|
191
188
|
|
192
189
|
def element_type
|
193
|
-
|
194
|
-
@options[:of]
|
195
|
-
else
|
190
|
+
if @options[:of].is_a?(Hash)
|
196
191
|
@options[:of].keys.first
|
192
|
+
else
|
193
|
+
@options[:of]
|
197
194
|
end
|
198
195
|
end
|
199
196
|
|
200
197
|
def element_options
|
201
|
-
|
202
|
-
{ type: element_type }
|
203
|
-
else
|
198
|
+
if @options[:of].is_a?(Hash)
|
204
199
|
@options[:of][element_type].dup.tap do |options|
|
205
200
|
options[:type] = element_type
|
206
201
|
end
|
202
|
+
else
|
203
|
+
{ type: element_type }
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
class MapTypeCaster < Base
|
209
|
+
def process(value)
|
210
|
+
return nil if value.nil?
|
211
|
+
|
212
|
+
if value.is_a? Hash
|
213
|
+
value
|
214
|
+
elsif value.respond_to? :to_hash
|
215
|
+
value.to_hash
|
216
|
+
elsif value.respond_to? :to_h
|
217
|
+
value.to_h
|
218
|
+
else
|
219
|
+
nil
|
207
220
|
end
|
208
221
|
end
|
209
222
|
end
|
@@ -213,7 +226,11 @@ module Dynamoid
|
|
213
226
|
if !value.respond_to?(:to_datetime)
|
214
227
|
nil
|
215
228
|
elsif value.is_a?(String)
|
216
|
-
dt =
|
229
|
+
dt = begin
|
230
|
+
DateTime.parse(value)
|
231
|
+
rescue StandardError
|
232
|
+
nil
|
233
|
+
end
|
217
234
|
if dt
|
218
235
|
seconds = string_utc_offset(value) || ApplicationTimeZone.utc_offset
|
219
236
|
offset = seconds_to_offset(seconds)
|
@@ -243,7 +260,8 @@ module Dynamoid
|
|
243
260
|
else
|
244
261
|
begin
|
245
262
|
value.to_date
|
246
|
-
rescue
|
263
|
+
rescue StandardError
|
264
|
+
nil
|
247
265
|
end
|
248
266
|
end
|
249
267
|
end
|
data/lib/dynamoid/undumping.rb
CHANGED
@@ -8,7 +8,7 @@ module Dynamoid
|
|
8
8
|
attributes.symbolize_keys
|
9
9
|
.select { |attribute| attributes_options.key?(attribute) }
|
10
10
|
.each do |attribute, value|
|
11
|
-
|
11
|
+
h[attribute] = undump_field(value, attributes_options[attribute])
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
@@ -32,6 +32,7 @@ module Dynamoid
|
|
32
32
|
when :number then NumberUndumper
|
33
33
|
when :set then SetUndumper
|
34
34
|
when :array then ArrayUndumper
|
35
|
+
when :map then MapUndumper
|
35
36
|
when :datetime then DateTimeUndumper
|
36
37
|
when :date then DateUndumper
|
37
38
|
when :raw then RawUndumper
|
@@ -45,6 +46,35 @@ module Dynamoid
|
|
45
46
|
end
|
46
47
|
end
|
47
48
|
|
49
|
+
module UndumpHashHelper
|
50
|
+
extend self
|
51
|
+
|
52
|
+
def undump_hash(hash)
|
53
|
+
{}.tap do |h|
|
54
|
+
hash.each { |key, value| h[key.to_sym] = undump_hash_value(value) }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def undump_hash_value(val)
|
61
|
+
case val
|
62
|
+
when BigDecimal
|
63
|
+
if Dynamoid::Config.convert_big_decimal
|
64
|
+
val.to_f
|
65
|
+
else
|
66
|
+
val
|
67
|
+
end
|
68
|
+
when Hash
|
69
|
+
undump_hash(val)
|
70
|
+
when Array
|
71
|
+
val.map { |v| undump_hash_value(v) }
|
72
|
+
else
|
73
|
+
val
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
48
78
|
class Base
|
49
79
|
def initialize(options)
|
50
80
|
@options = options
|
@@ -68,7 +98,7 @@ module Dynamoid
|
|
68
98
|
end
|
69
99
|
|
70
100
|
class SetUndumper < Base
|
71
|
-
ALLOWED_TYPES = [
|
101
|
+
ALLOWED_TYPES = %i[string integer number date datetime serialized].freeze
|
72
102
|
|
73
103
|
def process(set)
|
74
104
|
if @options.key?(:of)
|
@@ -94,26 +124,26 @@ module Dynamoid
|
|
94
124
|
end
|
95
125
|
|
96
126
|
def element_type
|
97
|
-
|
98
|
-
@options[:of]
|
99
|
-
else
|
127
|
+
if @options[:of].is_a?(Hash)
|
100
128
|
@options[:of].keys.first
|
129
|
+
else
|
130
|
+
@options[:of]
|
101
131
|
end
|
102
132
|
end
|
103
133
|
|
104
134
|
def element_options
|
105
|
-
|
106
|
-
{ type: element_type }
|
107
|
-
else
|
135
|
+
if @options[:of].is_a?(Hash)
|
108
136
|
@options[:of][element_type].dup.tap do |options|
|
109
137
|
options[:type] = element_type
|
110
138
|
end
|
139
|
+
else
|
140
|
+
{ type: element_type }
|
111
141
|
end
|
112
142
|
end
|
113
143
|
end
|
114
144
|
|
115
145
|
class ArrayUndumper < Base
|
116
|
-
ALLOWED_TYPES = [
|
146
|
+
ALLOWED_TYPES = %i[string integer number date datetime serialized].freeze
|
117
147
|
|
118
148
|
def process(array)
|
119
149
|
if @options.key?(:of)
|
@@ -139,24 +169,30 @@ module Dynamoid
|
|
139
169
|
end
|
140
170
|
|
141
171
|
def element_type
|
142
|
-
|
143
|
-
@options[:of]
|
144
|
-
else
|
172
|
+
if @options[:of].is_a?(Hash)
|
145
173
|
@options[:of].keys.first
|
174
|
+
else
|
175
|
+
@options[:of]
|
146
176
|
end
|
147
177
|
end
|
148
178
|
|
149
179
|
def element_options
|
150
|
-
|
151
|
-
{ type: element_type }
|
152
|
-
else
|
180
|
+
if @options[:of].is_a?(Hash)
|
153
181
|
@options[:of][element_type].dup.tap do |options|
|
154
182
|
options[:type] = element_type
|
155
183
|
end
|
184
|
+
else
|
185
|
+
{ type: element_type }
|
156
186
|
end
|
157
187
|
end
|
158
188
|
end
|
159
189
|
|
190
|
+
class MapUndumper < Base
|
191
|
+
def process(value)
|
192
|
+
UndumpHashHelper.undump_hash(value)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
160
196
|
class DateTimeUndumper < Base
|
161
197
|
def process(value)
|
162
198
|
return value if value.is_a?(Date) || value.is_a?(DateTime) || value.is_a?(Time)
|
@@ -190,36 +226,11 @@ module Dynamoid
|
|
190
226
|
class RawUndumper < Base
|
191
227
|
def process(value)
|
192
228
|
if value.is_a?(Hash)
|
193
|
-
undump_hash(value)
|
229
|
+
UndumpHashHelper.undump_hash(value)
|
194
230
|
else
|
195
231
|
value
|
196
232
|
end
|
197
233
|
end
|
198
|
-
|
199
|
-
private
|
200
|
-
|
201
|
-
def undump_hash(hash)
|
202
|
-
{}.tap do |h|
|
203
|
-
hash.each { |key, value| h[key.to_sym] = undump_hash_value(value) }
|
204
|
-
end
|
205
|
-
end
|
206
|
-
|
207
|
-
def undump_hash_value(val)
|
208
|
-
case val
|
209
|
-
when BigDecimal
|
210
|
-
if Dynamoid::Config.convert_big_decimal
|
211
|
-
val.to_f
|
212
|
-
else
|
213
|
-
val
|
214
|
-
end
|
215
|
-
when Hash
|
216
|
-
undump_hash(val)
|
217
|
-
when Array
|
218
|
-
val.map { |v| undump_hash_value(v) }
|
219
|
-
else
|
220
|
-
val
|
221
|
-
end
|
222
|
-
end
|
223
234
|
end
|
224
235
|
|
225
236
|
class SerializedUndumper < Base
|
@@ -233,7 +244,7 @@ module Dynamoid
|
|
233
244
|
end
|
234
245
|
|
235
246
|
class BooleanUndumper < Base
|
236
|
-
STRING_VALUES = [
|
247
|
+
STRING_VALUES = %w[t f].freeze
|
237
248
|
|
238
249
|
def process(value)
|
239
250
|
store_as_boolean = if @options[:store_as_native_boolean].nil?
|
data/lib/dynamoid/validations.rb
CHANGED
@@ -14,6 +14,7 @@ module Dynamoid
|
|
14
14
|
def save(options = {})
|
15
15
|
options.reverse_merge!(validate: true)
|
16
16
|
return false if options[:validate] && !valid?
|
17
|
+
|
17
18
|
super
|
18
19
|
end
|
19
20
|
|
@@ -30,6 +31,7 @@ module Dynamoid
|
|
30
31
|
# @since 0.2.0
|
31
32
|
def save!
|
32
33
|
raise Dynamoid::Errors::DocumentNotValid, self unless valid?
|
34
|
+
|
33
35
|
save(validate: false)
|
34
36
|
self
|
35
37
|
end
|
data/lib/dynamoid/version.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.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Josh Symonds
|
@@ -21,7 +21,7 @@ authors:
|
|
21
21
|
autorequire:
|
22
22
|
bindir: exe
|
23
23
|
cert_chain: []
|
24
|
-
date:
|
24
|
+
date: 2019-05-15 00:00:00.000000000 Z
|
25
25
|
dependencies:
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: activemodel
|
@@ -240,8 +240,15 @@ files:
|
|
240
240
|
- lib/dynamoid.rb
|
241
241
|
- lib/dynamoid/adapter.rb
|
242
242
|
- lib/dynamoid/adapter_plugin/aws_sdk_v3.rb
|
243
|
-
- lib/dynamoid/adapter_plugin/
|
244
|
-
- lib/dynamoid/adapter_plugin/
|
243
|
+
- lib/dynamoid/adapter_plugin/aws_sdk_v3/create_table.rb
|
244
|
+
- lib/dynamoid/adapter_plugin/aws_sdk_v3/item_updater.rb
|
245
|
+
- lib/dynamoid/adapter_plugin/aws_sdk_v3/middleware/backoff.rb
|
246
|
+
- lib/dynamoid/adapter_plugin/aws_sdk_v3/middleware/limit.rb
|
247
|
+
- lib/dynamoid/adapter_plugin/aws_sdk_v3/middleware/start_key.rb
|
248
|
+
- lib/dynamoid/adapter_plugin/aws_sdk_v3/query.rb
|
249
|
+
- lib/dynamoid/adapter_plugin/aws_sdk_v3/scan.rb
|
250
|
+
- lib/dynamoid/adapter_plugin/aws_sdk_v3/table.rb
|
251
|
+
- lib/dynamoid/adapter_plugin/aws_sdk_v3/until_past_table_status.rb
|
245
252
|
- lib/dynamoid/application_time_zone.rb
|
246
253
|
- lib/dynamoid/associations.rb
|
247
254
|
- lib/dynamoid/associations/association.rb
|
@@ -258,6 +265,10 @@ files:
|
|
258
265
|
- lib/dynamoid/config/options.rb
|
259
266
|
- lib/dynamoid/criteria.rb
|
260
267
|
- lib/dynamoid/criteria/chain.rb
|
268
|
+
- lib/dynamoid/criteria/ignored_conditions_detector.rb
|
269
|
+
- lib/dynamoid/criteria/key_fields_detector.rb
|
270
|
+
- lib/dynamoid/criteria/nonexistent_fields_detector.rb
|
271
|
+
- lib/dynamoid/criteria/overwritten_conditions_detector.rb
|
261
272
|
- lib/dynamoid/dirty.rb
|
262
273
|
- lib/dynamoid/document.rb
|
263
274
|
- lib/dynamoid/dumping.rb
|
@@ -271,6 +282,7 @@ files:
|
|
271
282
|
- lib/dynamoid/persistence.rb
|
272
283
|
- lib/dynamoid/primary_key_type_mapping.rb
|
273
284
|
- lib/dynamoid/railtie.rb
|
285
|
+
- lib/dynamoid/tasks.rb
|
274
286
|
- lib/dynamoid/tasks/database.rake
|
275
287
|
- lib/dynamoid/tasks/database.rb
|
276
288
|
- lib/dynamoid/type_casting.rb
|
@@ -297,7 +309,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
297
309
|
version: '0'
|
298
310
|
requirements: []
|
299
311
|
rubyforge_project:
|
300
|
-
rubygems_version: 2.6
|
312
|
+
rubygems_version: 2.7.6
|
301
313
|
signing_key:
|
302
314
|
specification_version: 4
|
303
315
|
summary: Dynamoid is an ORM for Amazon's DynamoDB
|