dynamoid 3.2.0 → 3.6.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 (78) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +111 -1
  3. data/README.md +580 -241
  4. data/lib/dynamoid.rb +2 -0
  5. data/lib/dynamoid/adapter.rb +15 -15
  6. data/lib/dynamoid/adapter_plugin/aws_sdk_v3.rb +82 -102
  7. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/batch_get_item.rb +108 -0
  8. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/create_table.rb +29 -16
  9. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/item_updater.rb +3 -2
  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 +15 -6
  14. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/scan.rb +15 -5
  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 +5 -3
  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 +4 -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 +65 -22
  25. data/lib/dynamoid/associations/single_association.rb +28 -1
  26. data/lib/dynamoid/components.rb +8 -3
  27. data/lib/dynamoid/config.rb +16 -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 +2 -1
  32. data/lib/dynamoid/criteria/chain.rb +418 -46
  33. data/lib/dynamoid/criteria/ignored_conditions_detector.rb +3 -3
  34. data/lib/dynamoid/criteria/key_fields_detector.rb +109 -32
  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 +239 -32
  38. data/lib/dynamoid/document.rb +130 -251
  39. data/lib/dynamoid/dumping.rb +9 -0
  40. data/lib/dynamoid/dynamodb_time_zone.rb +1 -0
  41. data/lib/dynamoid/fields.rb +246 -20
  42. data/lib/dynamoid/finders.rb +69 -32
  43. data/lib/dynamoid/identity_map.rb +6 -0
  44. data/lib/dynamoid/indexes.rb +76 -17
  45. data/lib/dynamoid/loadable.rb +31 -0
  46. data/lib/dynamoid/log/formatter.rb +26 -0
  47. data/lib/dynamoid/middleware/identity_map.rb +1 -0
  48. data/lib/dynamoid/persistence.rb +592 -122
  49. data/lib/dynamoid/persistence/import.rb +73 -0
  50. data/lib/dynamoid/persistence/save.rb +64 -0
  51. data/lib/dynamoid/persistence/update_fields.rb +63 -0
  52. data/lib/dynamoid/persistence/upsert.rb +60 -0
  53. data/lib/dynamoid/primary_key_type_mapping.rb +1 -0
  54. data/lib/dynamoid/railtie.rb +1 -0
  55. data/lib/dynamoid/tasks.rb +3 -1
  56. data/lib/dynamoid/tasks/database.rb +1 -0
  57. data/lib/dynamoid/type_casting.rb +12 -2
  58. data/lib/dynamoid/undumping.rb +8 -0
  59. data/lib/dynamoid/validations.rb +2 -0
  60. data/lib/dynamoid/version.rb +1 -1
  61. metadata +49 -71
  62. data/.coveralls.yml +0 -1
  63. data/.document +0 -5
  64. data/.gitignore +0 -74
  65. data/.rspec +0 -2
  66. data/.rubocop.yml +0 -71
  67. data/.rubocop_todo.yml +0 -55
  68. data/.travis.yml +0 -41
  69. data/Appraisals +0 -28
  70. data/Gemfile +0 -8
  71. data/Rakefile +0 -46
  72. data/Vagrantfile +0 -29
  73. data/docker-compose.yml +0 -7
  74. data/dynamoid.gemspec +0 -57
  75. data/gemfiles/rails_4_2.gemfile +0 -11
  76. data/gemfiles/rails_5_0.gemfile +0 -10
  77. data/gemfiles/rails_5_1.gemfile +0 -10
  78. data/gemfiles/rails_5_2.gemfile +0 -10
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Dynamoid #:nodoc:
3
+ module Dynamoid
4
4
  # This is the base module for all domain objects that need to be persisted to
5
5
  # the database as documents.
6
6
  module Document
@@ -17,28 +17,19 @@ module Dynamoid #:nodoc:
17
17
  end
18
18
 
19
19
  module ClassMethods
20
- # Set up table options, including naming it whatever you want, setting the id key, and manually overriding read and
21
- # write capacity.
22
- #
23
- # @param [Hash] options options to pass for this table
24
- # @option options [Symbol] :name the name for the table; this still gets namespaced
25
- # @option options [Symbol] :id id column for the table
26
- # @option options [Integer] :read_capacity set the read capacity for the table; does not work on existing tables
27
- # @option options [Integer] :write_capacity set the write capacity for the table; does not work on existing tables
28
- #
29
- # @since 0.4.0
20
+ # @private
30
21
  def table(options = {})
31
22
  self.options = options
32
23
  super if defined? super
33
24
  end
34
25
 
35
26
  def attr_readonly(*read_only_attributes)
36
- ActiveSupport::Deprecation.warn('[Dynamoid] .attr_readonly is deprecated! Call .find instead of')
37
27
  self.read_only_attributes.concat read_only_attributes.map(&:to_s)
38
28
  end
39
29
 
40
- # Returns the read_capacity for this table.
30
+ # Returns the read capacity for this table.
41
31
  #
32
+ # @return [Integer] read capacity units
42
33
  # @since 0.4.0
43
34
  def read_capacity
44
35
  options[:read_capacity] || Dynamoid::Config.read_capacity
@@ -46,91 +37,121 @@ module Dynamoid #:nodoc:
46
37
 
47
38
  # Returns the write_capacity for this table.
48
39
  #
40
+ # @return [Integer] write capacity units
49
41
  # @since 0.4.0
50
42
  def write_capacity
51
43
  options[:write_capacity] || Dynamoid::Config.write_capacity
52
44
  end
53
45
 
46
+ # Returns the billing (capacity) mode for this table.
47
+ #
48
+ # Could be either +provisioned+ or +on_demand+.
49
+ #
50
+ # @return [Symbol]
51
+ def capacity_mode
52
+ options[:capacity_mode] || Dynamoid::Config.capacity_mode
53
+ end
54
+
54
55
  # Returns the field name used to support STI for this table.
56
+ #
57
+ # Default field name is +type+ but it can be overrided in the +table+
58
+ # method call.
59
+ #
60
+ # User.inheritance_field # => :type
55
61
  def inheritance_field
56
62
  options[:inheritance_field] || :type
57
63
  end
58
64
 
59
- # Returns the id field for this class.
65
+ # Returns the hash key field name for this class.
60
66
  #
67
+ # By default +id+ field is used. But it can be overriden in the +table+
68
+ # method call.
69
+ #
70
+ # User.hash_key # => :id
71
+ #
72
+ # @return [Symbol] a hash key name
61
73
  # @since 0.4.0
62
74
  def hash_key
63
75
  options[:key] || :id
64
76
  end
65
77
 
66
- # Returns the number of items for this class.
78
+ # Return the count of items for this class.
79
+ #
80
+ # It returns aproximate value based on DynamoDB statistic. DynamoDB
81
+ # updates it periodicaly so the value can be no accurate.
67
82
  #
83
+ # It's a reletivly cheap operation and doesn't read all the items in a
84
+ # table. It makes just one HTTP request to DynamoDB.
85
+ #
86
+ # @return [Integer] items count in a table
68
87
  # @since 0.6.1
69
88
  def count
70
89
  Dynamoid.adapter.count(table_name)
71
90
  end
72
91
 
73
- # Initialize a new object and immediately save it to the database.
92
+ # Initialize a new object.
74
93
  #
75
- # @param [Hash] attrs Attributes with which to create the object.
94
+ # User.build(name: 'A')
76
95
  #
77
- # @return [Dynamoid::Document] the saved document
96
+ # Initialize an object and pass it into a block to set other attributes.
78
97
  #
79
- # @since 0.2.0
80
- def create(attrs = {})
81
- if attrs.is_a?(Array)
82
- attrs.map { |attr| create(attr) }
83
- else
84
- build(attrs).tap(&:save)
85
- end
86
- end
87
-
88
- # Initialize a new object and immediately save it to the database. Raise an exception if persistence failed.
98
+ # User.build(name: 'A') do |u|
99
+ # u.age = 21
100
+ # end
89
101
  #
90
- # @param [Hash] attrs Attributes with which to create the object.
102
+ # The only difference between +build+ and +new+ methods is that +build+
103
+ # supports STI (Single table inheritance) and looks at the inheritance
104
+ # field. So it can build a model of actual class. For instance:
91
105
  #
92
- # @return [Dynamoid::Document] the saved document
106
+ # class Employee
107
+ # include Dynamoid::Document
93
108
  #
94
- # @since 0.2.0
95
- def create!(attrs = {})
96
- if attrs.is_a?(Array)
97
- attrs.map { |attr| create!(attr) }
98
- else
99
- build(attrs).tap(&:save!)
100
- end
101
- end
102
-
103
- # Initialize a new object.
109
+ # field :type
110
+ # field :name
111
+ # end
104
112
  #
105
- # @param [Hash] attrs Attributes with which to create the object.
113
+ # class Manager < Employee
114
+ # end
106
115
  #
107
- # @return [Dynamoid::Document] the new document
116
+ # Employee.build(name: 'Alice', type: 'Manager') # => #<Manager:0x00007f945756e3f0 ...>
108
117
  #
118
+ # @param attrs [Hash] Attributes with which to create the document
119
+ # @param block [Proc] Block to process a document after initialization
120
+ # @return [Dynamoid::Document] the new document
109
121
  # @since 0.2.0
110
- def build(attrs = {})
111
- choose_right_class(attrs).new(attrs)
122
+ def build(attrs = {}, &block)
123
+ choose_right_class(attrs).new(attrs, &block)
112
124
  end
113
125
 
114
- # Does this object exist?
126
+ # Does this model exist in a table?
115
127
  #
116
- # Supports primary key in format that `find` call understands.
117
- # Multiple keys and single compound primary key should be passed only as Array explicitily.
128
+ # User.exists?('713') # => true
118
129
  #
119
- # Supports conditions in format that `where` call understands.
130
+ # If a range key is declared it should be specified in the following way:
120
131
  #
121
- # @param [Mixed] id_or_conditions the id of the object or a hash with the options to filter from.
132
+ # User.exists?([['713', 'range-key-value']]) # => true
122
133
  #
123
- # @return [Boolean] true/false
134
+ # It's possible to check existence of several models at once:
124
135
  #
125
- # @example With id
136
+ # User.exists?(['713', '714', '715'])
126
137
  #
127
- # Post.exist?(713)
128
- # Post.exist?([713, 210])
138
+ # Or in case when a range key is declared:
129
139
  #
130
- # @example With attributes conditions
140
+ # User.exists?(
141
+ # [
142
+ # ['713', 'range-key-value-1'],
143
+ # ['714', 'range-key-value-2'],
144
+ # ['715', 'range-key-value-3']
145
+ # ]
146
+ # )
131
147
  #
132
- # Post.exist?(version: 1, 'created_at.gt': Time.now - 1.day)
148
+ # It's also possible to specify models not with primary key but with
149
+ # conditions on the attributes (in the +where+ method style):
133
150
  #
151
+ # User.exists?(age: 20, 'created_at.gt': Time.now - 1.day)
152
+ #
153
+ # @param id_or_conditions [String|Array[String]|Array[Array]|Hash] the primary id of the model, a list of primary ids or a hash with the options to filter from.
154
+ # @return [true|false]
134
155
  # @since 0.2.0
135
156
  def exists?(id_or_conditions = {})
136
157
  case id_or_conditions
@@ -145,165 +166,12 @@ module Dynamoid #:nodoc:
145
166
  end
146
167
  end
147
168
 
148
- # Update document with provided values.
149
- # Instantiates document and saves changes. Runs validations and callbacks.
150
- #
151
- # @param [Scalar value] partition key
152
- # @param [Scalar value] sort key, optional
153
- # @param [Hash] attributes
154
- #
155
- # @return [Dynamoid::Doument] updated document
156
- #
157
- # @example Update document
158
- # Post.update(101, read: true)
159
- def update(hash_key, range_key_value = nil, attrs)
160
- model = find(hash_key, range_key: range_key_value, consistent_read: true)
161
- model.update_attributes(attrs)
162
- model
163
- end
164
-
165
- # Update document.
166
- # Uses efficient low-level `UpdateItem` API call.
167
- # Changes attibutes and loads new document version with one API call.
168
- # Doesn't run validations and callbacks. Can make conditional update.
169
- # If a document doesn't exist or specified conditions failed - returns `nil`
170
- #
171
- # @param [Scalar value] partition key
172
- # @param [Scalar value] sort key (optional)
173
- # @param [Hash] attributes
174
- # @param [Hash] conditions
175
- #
176
- # @return [Dynamoid::Document/nil] updated document
177
- #
178
- # @example Update document
179
- # Post.update_fields(101, read: true)
180
- #
181
- # @example Update document with condition
182
- # Post.update_fields(101, { read: true }, if: { version: 1 })
183
- def update_fields(hash_key_value, range_key_value = nil, attrs = {}, conditions = {})
184
- optional_params = [range_key_value, attrs, conditions].compact
185
- if optional_params.first.is_a?(Hash)
186
- range_key_value = nil
187
- attrs, conditions = optional_params[0..1]
188
- else
189
- range_key_value = optional_params.first
190
- attrs, conditions = optional_params[1..2]
191
- end
192
-
193
- options = if range_key
194
- value_casted = TypeCasting.cast_field(range_key_value, attributes[range_key])
195
- value_dumped = Dumping.dump_field(value_casted, attributes[range_key])
196
- { range_key: value_dumped }
197
- else
198
- {}
199
- end
200
-
201
- (conditions[:if_exists] ||= {})[hash_key] = hash_key_value
202
- options[:conditions] = conditions
203
-
204
- attrs = attrs.symbolize_keys
205
- if Dynamoid::Config.timestamps
206
- attrs[:updated_at] ||= DateTime.now.in_time_zone(Time.zone)
207
- end
208
-
209
- begin
210
- new_attrs = Dynamoid.adapter.update_item(table_name, hash_key_value, options) do |t|
211
- attrs.each do |k, v|
212
- value_casted = TypeCasting.cast_field(v, attributes[k])
213
- value_dumped = Dumping.dump_field(value_casted, attributes[k])
214
- t.set(k => value_dumped)
215
- end
216
- end
217
- attrs_undumped = Undumping.undump_attributes(new_attrs, attributes)
218
- new(attrs_undumped)
219
- rescue Dynamoid::Errors::ConditionalCheckFailedException
220
- end
221
- end
222
-
223
- # Update existing document or create new one.
224
- # Similar to `.update_fields`. The only diffirence is creating new document.
225
- #
226
- # Uses efficient low-level `UpdateItem` API call.
227
- # Changes attibutes and loads new document version with one API call.
228
- # Doesn't run validations and callbacks. Can make conditional update.
229
- # If specified conditions failed - returns `nil`
230
- #
231
- # @param [Scalar value] partition key
232
- # @param [Scalar value] sort key (optional)
233
- # @param [Hash] attributes
234
- # @param [Hash] conditions
235
- #
236
- # @return [Dynamoid::Document/nil] updated document
237
- #
238
- # @example Update document
239
- # Post.update(101, read: true)
240
- #
241
- # @example Update document
242
- # Post.upsert(101, read: true)
243
- def upsert(hash_key_value, range_key_value = nil, attrs = {}, conditions = {})
244
- optional_params = [range_key_value, attrs, conditions].compact
245
- if optional_params.first.is_a?(Hash)
246
- range_key_value = nil
247
- attrs, conditions = optional_params[0..1]
248
- else
249
- range_key_value = optional_params.first
250
- attrs, conditions = optional_params[1..2]
251
- end
252
-
253
- options = if range_key
254
- value_casted = TypeCasting.cast_field(range_key_value, attributes[range_key])
255
- value_dumped = Dumping.dump_field(value_casted, attributes[range_key])
256
- { range_key: value_dumped }
257
- else
258
- {}
259
- end
260
-
261
- options[:conditions] = conditions
262
-
263
- attrs = attrs.symbolize_keys
264
- if Dynamoid::Config.timestamps
265
- attrs[:updated_at] ||= DateTime.now.in_time_zone(Time.zone)
266
- end
267
-
268
- begin
269
- new_attrs = Dynamoid.adapter.update_item(table_name, hash_key_value, options) do |t|
270
- attrs.each do |k, v|
271
- value_casted = TypeCasting.cast_field(v, attributes[k])
272
- value_dumped = Dumping.dump_field(value_casted, attributes[k])
273
-
274
- t.set(k => value_dumped)
275
- end
276
- end
277
-
278
- attrs_undumped = Undumping.undump_attributes(new_attrs, attributes)
279
- new(attrs_undumped)
280
- rescue Dynamoid::Errors::ConditionalCheckFailedException
281
- end
282
- end
283
-
284
- def inc(hash_key_value, range_key_value = nil, counters)
285
- options = if range_key
286
- value_casted = TypeCasting.cast_field(range_key_value, attributes[range_key])
287
- value_dumped = Dumping.dump_field(value_casted, attributes[range_key])
288
- { range_key: value_dumped }
289
- else
290
- {}
291
- end
292
-
293
- Dynamoid.adapter.update_item(table_name, hash_key_value, options) do |t|
294
- counters.each do |k, v|
295
- value_casted = TypeCasting.cast_field(v, attributes[k])
296
- value_dumped = Dumping.dump_field(value_casted, attributes[k])
297
-
298
- t.add(k => value_dumped)
299
- end
300
- end
301
- end
302
-
169
+ # @private
303
170
  def deep_subclasses
304
171
  subclasses + subclasses.map(&:deep_subclasses).flatten
305
172
  end
306
173
 
174
+ # @private
307
175
  def choose_right_class(attrs)
308
176
  attrs[inheritance_field] ? attrs[inheritance_field].constantize : self
309
177
  end
@@ -311,41 +179,50 @@ module Dynamoid #:nodoc:
311
179
 
312
180
  # Initialize a new object.
313
181
  #
314
- # @param [Hash] attrs Attributes with which to create the object.
182
+ # User.new(name: 'A')
183
+ #
184
+ # Initialize an object and pass it into a block to set other attributes.
185
+ #
186
+ # User.new(name: 'A') do |u|
187
+ # u.age = 21
188
+ # end
315
189
  #
190
+ # @param attrs [Hash] Attributes with which to create the document
191
+ # @param block [Proc] Block to process a document after initialization
316
192
  # @return [Dynamoid::Document] the new document
317
193
  #
318
194
  # @since 0.2.0
319
- def initialize(attrs = {})
195
+ def initialize(attrs = {}, &block)
320
196
  run_callbacks :initialize do
321
197
  @new_record = true
322
198
  @attributes ||= {}
323
199
  @associations ||= {}
324
200
  @attributes_before_type_cast ||= {}
325
201
 
326
- attrs_with_defaults = {}
327
- self.class.attributes.each do |attribute, options|
328
- attrs_with_defaults[attribute] = if attrs.key?(attribute)
329
- attrs[attribute]
330
- elsif options.key?(:default)
331
- evaluate_default_value(options[:default])
332
- end
202
+ attrs_with_defaults = self.class.attributes.each_with_object({}) do |(attribute, options), res|
203
+ if attrs.key?(attribute)
204
+ res[attribute] = attrs[attribute]
205
+ elsif options.key?(:default)
206
+ res[attribute] = evaluate_default_value(options[:default])
207
+ end
333
208
  end
334
209
 
335
210
  attrs_virtual = attrs.slice(*(attrs.keys - self.class.attributes.keys))
336
211
 
337
212
  load(attrs_with_defaults.merge(attrs_virtual))
338
- end
339
- end
340
213
 
341
- def load(attrs)
342
- attrs.each do |key, value|
343
- send("#{key}=", value) if respond_to?("#{key}=")
214
+ if block
215
+ block.call(self)
216
+ end
344
217
  end
345
218
  end
346
219
 
347
- # An object is equal to another object if their ids are equal.
220
+ # Check equality of two models.
221
+ #
222
+ # A model is equal to another model only if their primary keys (hash key
223
+ # and optionaly range key) are equal.
348
224
  #
225
+ # @return [true|false]
349
226
  # @since 0.2.0
350
227
  def ==(other)
351
228
  if self.class.identity_map_on?
@@ -357,54 +234,54 @@ module Dynamoid #:nodoc:
357
234
  end
358
235
  end
359
236
 
237
+ # Check equality of two models.
238
+ #
239
+ # Works exactly like +==+ does.
240
+ #
241
+ # @return [true|false]
360
242
  def eql?(other)
361
243
  self == other
362
244
  end
363
245
 
364
- def hash
365
- hash_key.hash ^ range_value.hash
366
- end
367
-
368
- # Reload an object from the database -- if you suspect the object has changed in the datastore and you need those
369
- # changes to be reflected immediately, you would call this method. This is a consistent read.
246
+ # Generate an Integer hash value for this model.
370
247
  #
371
- # @return [Dynamoid::Document] the document this method was called on
248
+ # Hash value is based on primary key. So models can be used safely as a
249
+ # +Hash+ keys.
372
250
  #
373
- # @since 0.2.0
374
- def reload
375
- options = { consistent_read: true }
376
-
377
- if self.class.range_key
378
- options[:range_key] = range_value
379
- end
380
-
381
- self.attributes = self.class.find(hash_key, options).attributes
382
- @associations.values.each(&:reset)
383
- self
251
+ # @return [Integer]
252
+ def hash
253
+ hash_key.hash ^ range_value.hash
384
254
  end
385
255
 
386
- # Return an object's hash key, regardless of what it might be called to the object.
256
+ # Return a model's hash key value.
387
257
  #
388
258
  # @since 0.4.0
389
259
  def hash_key
390
- send(self.class.hash_key)
260
+ self[self.class.hash_key.to_sym]
391
261
  end
392
262
 
393
- # Assign an object's hash key, regardless of what it might be called to the object.
263
+ # Assign a model's hash key value, regardless of what it might be called to
264
+ # the object.
394
265
  #
395
266
  # @since 0.4.0
396
267
  def hash_key=(value)
397
- send("#{self.class.hash_key}=", value)
268
+ self[self.class.hash_key.to_sym] = value
398
269
  end
399
270
 
271
+ # Return a model's range key value.
272
+ #
273
+ # Returns +nil+ if a range key isn't declared for a model.
400
274
  def range_value
401
- if range_key = self.class.range_key
402
- send(range_key)
275
+ if self.class.range_key
276
+ self[self.class.range_key.to_sym]
403
277
  end
404
278
  end
405
279
 
280
+ # Assign a model's range key value.
406
281
  def range_value=(value)
407
- send("#{self.class.range_key}=", value)
282
+ if self.class.range_key
283
+ self[self.class.range_key.to_sym] = value
284
+ end
408
285
  end
409
286
 
410
287
  private
@@ -416,7 +293,7 @@ module Dynamoid #:nodoc:
416
293
  # Evaluates the default value given, this is used by undump
417
294
  # when determining the value of the default given for a field options.
418
295
  #
419
- # @param [Object] :value the attribute's default value
296
+ # @param val [Object] the attribute's default value
420
297
  def evaluate_default_value(val)
421
298
  if val.respond_to?(:call)
422
299
  val.call
@@ -428,3 +305,5 @@ module Dynamoid #:nodoc:
428
305
  end
429
306
  end
430
307
  end
308
+
309
+ ActiveSupport.run_load_hooks(:dynamoid, Dynamoid::Document)