dynamoid 3.5.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 (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