dynamoid 3.5.0 → 3.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +35 -4
  3. data/README.md +24 -18
  4. data/lib/dynamoid.rb +1 -0
  5. data/lib/dynamoid/adapter.rb +7 -4
  6. data/lib/dynamoid/adapter_plugin/aws_sdk_v3.rb +14 -11
  7. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/batch_get_item.rb +1 -0
  8. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/create_table.rb +8 -7
  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 +1 -0
  11. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/middleware/limit.rb +1 -0
  12. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/middleware/start_key.rb +1 -0
  13. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/query.rb +1 -0
  14. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/scan.rb +1 -0
  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 +1 -0
  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 +1 -0
  27. data/lib/dynamoid/config.rb +3 -2
  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 +1 -0
  32. data/lib/dynamoid/criteria/chain.rb +353 -33
  33. data/lib/dynamoid/criteria/ignored_conditions_detector.rb +1 -0
  34. data/lib/dynamoid/criteria/key_fields_detector.rb +10 -1
  35. data/lib/dynamoid/criteria/nonexistent_fields_detector.rb +1 -0
  36. data/lib/dynamoid/criteria/overwritten_conditions_detector.rb +1 -0
  37. data/lib/dynamoid/dirty.rb +71 -16
  38. data/lib/dynamoid/document.rb +123 -42
  39. data/lib/dynamoid/dumping.rb +9 -0
  40. data/lib/dynamoid/dynamodb_time_zone.rb +1 -0
  41. data/lib/dynamoid/fields.rb +189 -16
  42. data/lib/dynamoid/finders.rb +65 -28
  43. data/lib/dynamoid/identity_map.rb +6 -0
  44. data/lib/dynamoid/indexes.rb +74 -15
  45. data/lib/dynamoid/log/formatter.rb +26 -0
  46. data/lib/dynamoid/middleware/identity_map.rb +1 -0
  47. data/lib/dynamoid/persistence.rb +452 -106
  48. data/lib/dynamoid/persistence/import.rb +1 -0
  49. data/lib/dynamoid/persistence/save.rb +1 -0
  50. data/lib/dynamoid/persistence/update_fields.rb +1 -0
  51. data/lib/dynamoid/persistence/upsert.rb +1 -0
  52. data/lib/dynamoid/primary_key_type_mapping.rb +1 -0
  53. data/lib/dynamoid/railtie.rb +1 -0
  54. data/lib/dynamoid/tasks/database.rb +1 -0
  55. data/lib/dynamoid/type_casting.rb +12 -0
  56. data/lib/dynamoid/undumping.rb +8 -0
  57. data/lib/dynamoid/validations.rb +2 -0
  58. data/lib/dynamoid/version.rb +1 -1
  59. metadata +7 -19
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Dynamoid
4
4
  module Criteria
5
+ # @private
5
6
  class IgnoredConditionsDetector
6
7
  def initialize(conditions)
7
8
  @conditions = conditions
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Dynamoid #:nodoc:
3
+ module Dynamoid
4
4
  module Criteria
5
+ # @private
5
6
  class KeyFieldsDetector
6
7
  class Query
7
8
  def initialize(query_hash)
@@ -10,6 +11,10 @@ module Dynamoid #:nodoc:
10
11
  @fields = query_hash.keys.map(&:to_s).map { |s| s.split('.').first }
11
12
  end
12
13
 
14
+ def contain_only?(field_names)
15
+ (@fields - field_names.map(&:to_s)).blank?
16
+ end
17
+
13
18
  def contain?(field_name)
14
19
  @fields.include?(field_name.to_s)
15
20
  end
@@ -26,6 +31,10 @@ module Dynamoid #:nodoc:
26
31
  @result = find_keys_in_query
27
32
  end
28
33
 
34
+ def non_key_present?
35
+ !@query.contain_only?([hash_key, range_key].compact)
36
+ end
37
+
29
38
  def key_present?
30
39
  @result.present?
31
40
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Dynamoid
4
4
  module Criteria
5
+ # @private
5
6
  class NonexistentFieldsDetector
6
7
  def initialize(conditions, source)
7
8
  @conditions = conditions
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Dynamoid
4
4
  module Criteria
5
+ # @private
5
6
  class OverwrittenConditionsDetector
6
7
  def initialize(conditions, conditions_new)
7
8
  @conditions = conditions
@@ -22,6 +22,7 @@ module Dynamoid
22
22
  attribute_method_affix prefix: 'restore_', suffix: '!'
23
23
  end
24
24
 
25
+ # @private
25
26
  module ClassMethods
26
27
  def update_fields(*)
27
28
  if model = super
@@ -44,6 +45,7 @@ module Dynamoid
44
45
  end
45
46
  end
46
47
 
48
+ # @private
47
49
  def save(*)
48
50
  if status = super
49
51
  changes_applied
@@ -51,24 +53,28 @@ module Dynamoid
51
53
  status
52
54
  end
53
55
 
56
+ # @private
54
57
  def save!(*)
55
58
  super.tap do
56
59
  changes_applied
57
60
  end
58
61
  end
59
62
 
63
+ # @private
60
64
  def update(*)
61
65
  super.tap do
62
66
  clear_changes_information
63
67
  end
64
68
  end
65
69
 
70
+ # @private
66
71
  def update!(*)
67
72
  super.tap do
68
73
  clear_changes_information
69
74
  end
70
75
  end
71
76
 
77
+ # @private
72
78
  def reload(*)
73
79
  super.tap do
74
80
  clear_changes_information
@@ -78,17 +84,22 @@ module Dynamoid
78
84
  # Returns +true+ if any attribute have unsaved changes, +false+ otherwise.
79
85
  #
80
86
  # person.changed? # => false
81
- # person.name = 'bob'
87
+ # person.name = 'Bob'
82
88
  # person.changed? # => true
89
+ #
90
+ # @return [true|false]
83
91
  def changed?
84
92
  changed_attributes.present?
85
93
  end
86
94
 
87
- # Returns an array with the name of the attributes with unsaved changes.
95
+ # Returns an array with names of the attributes with unsaved changes.
88
96
  #
97
+ # person = Person.new
89
98
  # person.changed # => []
90
- # person.name = 'bob'
99
+ # person.name = 'Bob'
91
100
  # person.changed # => ["name"]
101
+ #
102
+ # @return [Array[String]]
92
103
  def changed
93
104
  changed_attributes.keys
94
105
  end
@@ -97,18 +108,22 @@ module Dynamoid
97
108
  # and new values like <tt>attr => [original value, new value]</tt>.
98
109
  #
99
110
  # person.changes # => {}
100
- # person.name = 'bob'
101
- # person.changes # => { "name" => ["bill", "bob"] }
111
+ # person.name = 'Bob'
112
+ # person.changes # => { "name" => ["Bill", "Bob"] }
113
+ #
114
+ # @return [ActiveSupport::HashWithIndifferentAccess]
102
115
  def changes
103
116
  ActiveSupport::HashWithIndifferentAccess[changed.map { |attr| [attr, attribute_change(attr)] }]
104
117
  end
105
118
 
106
119
  # Returns a hash of attributes that were changed before the model was saved.
107
120
  #
108
- # person.name # => "bob"
109
- # person.name = 'robert'
121
+ # person.name # => "Bob"
122
+ # person.name = 'Robert'
110
123
  # person.save
111
- # person.previous_changes # => {"name" => ["bob", "robert"]}
124
+ # person.previous_changes # => {"name" => ["Bob", "Robert"]}
125
+ #
126
+ # @return [ActiveSupport::HashWithIndifferentAccess]
112
127
  def previous_changes
113
128
  @previously_changed ||= ActiveSupport::HashWithIndifferentAccess.new
114
129
  end
@@ -116,15 +131,28 @@ module Dynamoid
116
131
  # Returns a hash of the attributes with unsaved changes indicating their original
117
132
  # values like <tt>attr => original value</tt>.
118
133
  #
119
- # person.name # => "bob"
120
- # person.name = 'robert'
121
- # person.changed_attributes # => {"name" => "bob"}
134
+ # person.name # => "Bob"
135
+ # person.name = 'Robert'
136
+ # person.changed_attributes # => {"name" => "Bob"}
137
+ #
138
+ # @return [ActiveSupport::HashWithIndifferentAccess]
122
139
  def changed_attributes
123
140
  @changed_attributes ||= ActiveSupport::HashWithIndifferentAccess.new
124
141
  end
125
142
 
126
143
  # Handle <tt>*_changed?</tt> for +method_missing+.
127
- def attribute_changed?(attr, options = {}) #:nodoc:
144
+ #
145
+ # person.attribute_changed?(:name) # => true
146
+ # person.attribute_changed?(:name, from: 'Alice')
147
+ # person.attribute_changed?(:name, to: 'Bob')
148
+ # person.attribute_changed?(:name, from: 'Alice', to: 'Bod')
149
+ #
150
+ # @private
151
+ # @param attr [Symbol] attribute name
152
+ # @param options [Hash] conditions on +from+ and +to+ value (optional)
153
+ # @option options [Symbol] :from previous attribute value
154
+ # @option options [Symbol] :to current attribute value
155
+ def attribute_changed?(attr, options = {})
128
156
  result = changes_include?(attr)
129
157
  result &&= options[:to] == __send__(attr) if options.key?(:to)
130
158
  result &&= options[:from] == changed_attributes[attr] if options.key?(:from)
@@ -132,21 +160,48 @@ module Dynamoid
132
160
  end
133
161
 
134
162
  # Handle <tt>*_was</tt> for +method_missing+.
135
- def attribute_was(attr) # :nodoc:
163
+ #
164
+ # person = Person.create(name: 'Alice')
165
+ # person.name = 'Bob'
166
+ # person.attribute_was(:name) # => "Alice"
167
+ #
168
+ # @private
169
+ # @param attr [Symbol] attribute name
170
+ def attribute_was(attr)
136
171
  attribute_changed?(attr) ? changed_attributes[attr] : __send__(attr)
137
172
  end
138
173
 
139
174
  # Restore all previous data of the provided attributes.
175
+ #
176
+ # @param attributes [Array[Symbol]] a list of attribute names
140
177
  def restore_attributes(attributes = changed)
141
178
  attributes.each { |attr| restore_attribute! attr }
142
179
  end
143
180
 
144
181
  # Handles <tt>*_previously_changed?</tt> for +method_missing+.
145
- def attribute_previously_changed?(attr) #:nodoc:
182
+ #
183
+ # person = Person.create(name: 'Alice')
184
+ # person.name = 'Bob'
185
+ # person.save
186
+ # person.attribute_changed?(:name) # => true
187
+ #
188
+ # @private
189
+ # @param attr [Symbol] attribute name
190
+ # @return [true|false]
191
+ def attribute_previously_changed?(attr)
146
192
  previous_changes_include?(attr)
147
193
  end
148
194
 
149
195
  # Handles <tt>*_previous_change</tt> for +method_missing+.
196
+ #
197
+ # person = Person.create(name: 'Alice')
198
+ # person.name = 'Bob'
199
+ # person.save
200
+ # person.attribute_previously_changed(:name) # => ["Alice", "Bob"]
201
+ #
202
+ # @private
203
+ # @param attr [Symbol]
204
+ # @return [Array]
150
205
  def attribute_previous_change(attr)
151
206
  previous_changes[attr] if attribute_previously_changed?(attr)
152
207
  end
@@ -204,7 +259,7 @@ module Dynamoid
204
259
 
205
260
  # This is necessary because `changed_attributes` might be overridden in
206
261
  # other implemntations (e.g. in `ActiveRecord`)
207
- alias attributes_changed_by_setter changed_attributes # :nodoc:
262
+ alias attributes_changed_by_setter changed_attributes
208
263
 
209
264
  # Force an attribute to have a particular "before" value
210
265
  def set_attribute_was(attr, old_value)
@@ -212,7 +267,7 @@ module Dynamoid
212
267
  end
213
268
 
214
269
  # Remove changes information for the provided attributes.
215
- def clear_attribute_changes(attributes) # :doc:
270
+ def clear_attribute_changes(attributes)
216
271
  attributes_changed_by_setter.except!(*attributes)
217
272
  end
218
273
  end
@@ -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,31 +37,53 @@ 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
 
54
46
  # Returns the billing (capacity) mode for this table.
55
- # Could be either :provisioned or :on_demand
47
+ #
48
+ # Could be either +provisioned+ or +on_demand+.
49
+ #
50
+ # @return [Symbol]
56
51
  def capacity_mode
57
52
  options[:capacity_mode] || Dynamoid::Config.capacity_mode
58
53
  end
59
54
 
60
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
61
61
  def inheritance_field
62
62
  options[:inheritance_field] || :type
63
63
  end
64
64
 
65
- # Returns the id field for this class.
65
+ # Returns the hash key field name for this class.
66
+ #
67
+ # By default +id+ field is used. But it can be overriden in the +table+
68
+ # method call.
66
69
  #
70
+ # User.hash_key # => :id
71
+ #
72
+ # @return [Symbol] a hash key name
67
73
  # @since 0.4.0
68
74
  def hash_key
69
75
  options[:key] || :id
70
76
  end
71
77
 
72
- # 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.
73
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
74
87
  # @since 0.6.1
75
88
  def count
76
89
  Dynamoid.adapter.count(table_name)
@@ -78,35 +91,67 @@ module Dynamoid #:nodoc:
78
91
 
79
92
  # Initialize a new object.
80
93
  #
81
- # @param [Hash] attrs Attributes with which to create the object.
94
+ # User.build(name: 'A')
82
95
  #
83
- # @return [Dynamoid::Document] the new document
96
+ # Initialize an object and pass it into a block to set other attributes.
97
+ #
98
+ # User.build(name: 'A') do |u|
99
+ # u.age = 21
100
+ # end
101
+ #
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:
105
+ #
106
+ # class Employee
107
+ # include Dynamoid::Document
108
+ #
109
+ # field :type
110
+ # field :name
111
+ # end
84
112
  #
113
+ # class Manager < Employee
114
+ # end
115
+ #
116
+ # Employee.build(name: 'Alice', type: 'Manager') # => #<Manager:0x00007f945756e3f0 ...>
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
85
121
  # @since 0.2.0
86
- def build(attrs = {})
87
- choose_right_class(attrs).new(attrs)
122
+ def build(attrs = {}, &block)
123
+ choose_right_class(attrs).new(attrs, &block)
88
124
  end
89
125
 
90
- # Does this object exist?
126
+ # Does this model exist in a table?
127
+ #
128
+ # User.exists?('713') # => true
91
129
  #
92
- # Supports primary key in format that `find` call understands.
93
- # Multiple keys and single compound primary key should be passed only as Array explicitily.
130
+ # If a range key is declared it should be specified in the following way:
94
131
  #
95
- # Supports conditions in format that `where` call understands.
132
+ # User.exists?([['713', 'range-key-value']]) # => true
96
133
  #
97
- # @param [Mixed] id_or_conditions the id of the object or a hash with the options to filter from.
134
+ # It's possible to check existence of several models at once:
98
135
  #
99
- # @return [Boolean] true/false
136
+ # User.exists?(['713', '714', '715'])
100
137
  #
101
- # @example With id
138
+ # Or in case when a range key is declared:
102
139
  #
103
- # Post.exist?(713)
104
- # Post.exist?([713, 210])
140
+ # User.exists?(
141
+ # [
142
+ # ['713', 'range-key-value-1'],
143
+ # ['714', 'range-key-value-2'],
144
+ # ['715', 'range-key-value-3']
145
+ # ]
146
+ # )
105
147
  #
106
- # @example With attributes conditions
148
+ # It's also possible to specify models not with primary key but with
149
+ # conditions on the attributes (in the +where+ method style):
107
150
  #
108
- # Post.exist?(version: 1, 'created_at.gt': Time.now - 1.day)
151
+ # User.exists?(age: 20, 'created_at.gt': Time.now - 1.day)
109
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]
110
155
  # @since 0.2.0
111
156
  def exists?(id_or_conditions = {})
112
157
  case id_or_conditions
@@ -121,10 +166,12 @@ module Dynamoid #:nodoc:
121
166
  end
122
167
  end
123
168
 
169
+ # @private
124
170
  def deep_subclasses
125
171
  subclasses + subclasses.map(&:deep_subclasses).flatten
126
172
  end
127
173
 
174
+ # @private
128
175
  def choose_right_class(attrs)
129
176
  attrs[inheritance_field] ? attrs[inheritance_field].constantize : self
130
177
  end
@@ -132,12 +179,20 @@ module Dynamoid #:nodoc:
132
179
 
133
180
  # Initialize a new object.
134
181
  #
135
- # @param [Hash] attrs Attributes with which to create the object.
182
+ # User.new(name: 'A')
136
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
189
+ #
190
+ # @param attrs [Hash] Attributes with which to create the document
191
+ # @param block [Proc] Block to process a document after initialization
137
192
  # @return [Dynamoid::Document] the new document
138
193
  #
139
194
  # @since 0.2.0
140
- def initialize(attrs = {})
195
+ def initialize(attrs = {}, &block)
141
196
  run_callbacks :initialize do
142
197
  @new_record = true
143
198
  @attributes ||= {}
@@ -155,11 +210,19 @@ module Dynamoid #:nodoc:
155
210
  attrs_virtual = attrs.slice(*(attrs.keys - self.class.attributes.keys))
156
211
 
157
212
  load(attrs_with_defaults.merge(attrs_virtual))
213
+
214
+ if block
215
+ block.call(self)
216
+ end
158
217
  end
159
218
  end
160
219
 
161
- # An object is equal to another object if their ids are equal.
220
+ # Check equality of two models.
162
221
  #
222
+ # A model is equal to another model only if their primary keys (hash key
223
+ # and optionaly range key) are equal.
224
+ #
225
+ # @return [true|false]
163
226
  # @since 0.2.0
164
227
  def ==(other)
165
228
  if self.class.identity_map_on?
@@ -171,36 +234,54 @@ module Dynamoid #:nodoc:
171
234
  end
172
235
  end
173
236
 
237
+ # Check equality of two models.
238
+ #
239
+ # Works exactly like +==+ does.
240
+ #
241
+ # @return [true|false]
174
242
  def eql?(other)
175
243
  self == other
176
244
  end
177
245
 
246
+ # Generate an Integer hash value for this model.
247
+ #
248
+ # Hash value is based on primary key. So models can be used safely as a
249
+ # +Hash+ keys.
250
+ #
251
+ # @return [Integer]
178
252
  def hash
179
253
  hash_key.hash ^ range_value.hash
180
254
  end
181
255
 
182
- # Return an object's hash key, regardless of what it might be called to the object.
256
+ # Return a model's hash key value.
183
257
  #
184
258
  # @since 0.4.0
185
259
  def hash_key
186
- send(self.class.hash_key)
260
+ self[self.class.hash_key.to_sym]
187
261
  end
188
262
 
189
- # 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.
190
265
  #
191
266
  # @since 0.4.0
192
267
  def hash_key=(value)
193
- send("#{self.class.hash_key}=", value)
268
+ self[self.class.hash_key.to_sym] = value
194
269
  end
195
270
 
271
+ # Return a model's range key value.
272
+ #
273
+ # Returns +nil+ if a range key isn't declared for a model.
196
274
  def range_value
197
- if range_key = self.class.range_key
198
- send(range_key)
275
+ if self.class.range_key
276
+ self[self.class.range_key.to_sym]
199
277
  end
200
278
  end
201
279
 
280
+ # Assign a model's range key value.
202
281
  def range_value=(value)
203
- send("#{self.class.range_key}=", value)
282
+ if self.class.range_key
283
+ self[self.class.range_key.to_sym] = value
284
+ end
204
285
  end
205
286
 
206
287
  private
@@ -212,7 +293,7 @@ module Dynamoid #:nodoc:
212
293
  # Evaluates the default value given, this is used by undump
213
294
  # when determining the value of the default given for a field options.
214
295
  #
215
- # @param [Object] :value the attribute's default value
296
+ # @param val [Object] the attribute's default value
216
297
  def evaluate_default_value(val)
217
298
  if val.respond_to?(:call)
218
299
  val.call