dynamoid 3.4.1 → 3.5.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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +24 -0
  3. data/lib/dynamoid/adapter.rb +2 -2
  4. data/lib/dynamoid/adapter_plugin/aws_sdk_v3.rb +23 -23
  5. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/batch_get_item.rb +2 -0
  6. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/create_table.rb +1 -1
  7. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/middleware/backoff.rb +1 -2
  8. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/middleware/limit.rb +1 -3
  9. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/middleware/start_key.rb +1 -2
  10. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/query.rb +3 -2
  11. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/scan.rb +3 -2
  12. data/lib/dynamoid/adapter_plugin/aws_sdk_v3/until_past_table_status.rb +1 -1
  13. data/lib/dynamoid/config.rb +2 -3
  14. data/lib/dynamoid/criteria.rb +1 -1
  15. data/lib/dynamoid/criteria/chain.rb +37 -12
  16. data/lib/dynamoid/criteria/ignored_conditions_detector.rb +2 -3
  17. data/lib/dynamoid/criteria/key_fields_detector.rb +7 -8
  18. data/lib/dynamoid/criteria/nonexistent_fields_detector.rb +2 -2
  19. data/lib/dynamoid/criteria/overwritten_conditions_detector.rb +0 -1
  20. data/lib/dynamoid/dirty.rb +50 -50
  21. data/lib/dynamoid/document.rb +2 -1
  22. data/lib/dynamoid/fields.rb +14 -1
  23. data/lib/dynamoid/finders.rb +4 -4
  24. data/lib/dynamoid/indexes.rb +2 -2
  25. data/lib/dynamoid/persistence.rb +32 -6
  26. data/lib/dynamoid/persistence/upsert.rb +0 -1
  27. data/lib/dynamoid/tasks.rb +3 -1
  28. data/lib/dynamoid/type_casting.rb +0 -2
  29. data/lib/dynamoid/version.rb +1 -1
  30. metadata +40 -56
  31. data/.coveralls.yml +0 -1
  32. data/.document +0 -5
  33. data/.gitignore +0 -74
  34. data/.rspec +0 -2
  35. data/.rubocop.yml +0 -71
  36. data/.rubocop_todo.yml +0 -55
  37. data/.travis.yml +0 -44
  38. data/Appraisals +0 -22
  39. data/Gemfile +0 -8
  40. data/Rakefile +0 -46
  41. data/Vagrantfile +0 -29
  42. data/docker-compose.yml +0 -7
  43. data/dynamoid.gemspec +0 -57
  44. data/gemfiles/rails_4_2.gemfile +0 -9
  45. data/gemfiles/rails_5_0.gemfile +0 -8
  46. data/gemfiles/rails_5_1.gemfile +0 -8
  47. data/gemfiles/rails_5_2.gemfile +0 -8
  48. data/gemfiles/rails_6_0.gemfile +0 -8
@@ -153,67 +153,67 @@ module Dynamoid
153
153
 
154
154
  private
155
155
 
156
- def changes_include?(attr_name)
157
- attributes_changed_by_setter.include?(attr_name)
158
- end
159
- alias attribute_changed_by_setter? changes_include?
160
-
161
- # Removes current changes and makes them accessible through +previous_changes+.
162
- def changes_applied # :doc:
163
- @previously_changed = changes
164
- @changed_attributes = ActiveSupport::HashWithIndifferentAccess.new
165
- end
156
+ def changes_include?(attr_name)
157
+ attributes_changed_by_setter.include?(attr_name)
158
+ end
159
+ alias attribute_changed_by_setter? changes_include?
166
160
 
167
- # Clear all dirty data: current changes and previous changes.
168
- def clear_changes_information # :doc:
169
- @previously_changed = ActiveSupport::HashWithIndifferentAccess.new
170
- @changed_attributes = ActiveSupport::HashWithIndifferentAccess.new
171
- end
161
+ # Removes current changes and makes them accessible through +previous_changes+.
162
+ def changes_applied # :doc:
163
+ @previously_changed = changes
164
+ @changed_attributes = ActiveSupport::HashWithIndifferentAccess.new
165
+ end
172
166
 
173
- # Handle <tt>*_change</tt> for +method_missing+.
174
- def attribute_change(attr)
175
- [changed_attributes[attr], __send__(attr)] if attribute_changed?(attr)
176
- end
167
+ # Clear all dirty data: current changes and previous changes.
168
+ def clear_changes_information # :doc:
169
+ @previously_changed = ActiveSupport::HashWithIndifferentAccess.new
170
+ @changed_attributes = ActiveSupport::HashWithIndifferentAccess.new
171
+ end
177
172
 
178
- # Handle <tt>*_will_change!</tt> for +method_missing+.
179
- def attribute_will_change!(attr)
180
- return if attribute_changed?(attr)
173
+ # Handle <tt>*_change</tt> for +method_missing+.
174
+ def attribute_change(attr)
175
+ [changed_attributes[attr], __send__(attr)] if attribute_changed?(attr)
176
+ end
181
177
 
182
- begin
183
- value = __send__(attr)
184
- value = value.duplicable? ? value.clone : value
185
- rescue TypeError, NoMethodError
186
- end
178
+ # Handle <tt>*_will_change!</tt> for +method_missing+.
179
+ def attribute_will_change!(attr)
180
+ return if attribute_changed?(attr)
187
181
 
188
- set_attribute_was(attr, value)
182
+ begin
183
+ value = __send__(attr)
184
+ value = value.duplicable? ? value.clone : value
185
+ rescue TypeError, NoMethodError
189
186
  end
190
187
 
191
- # Handle <tt>restore_*!</tt> for +method_missing+.
192
- def restore_attribute!(attr)
193
- if attribute_changed?(attr)
194
- __send__("#{attr}=", changed_attributes[attr])
195
- clear_attribute_changes([attr])
196
- end
197
- end
188
+ set_attribute_was(attr, value)
189
+ end
198
190
 
199
- # Returns +true+ if attr_name were changed before the model was saved,
200
- # +false+ otherwise.
201
- def previous_changes_include?(attr_name)
202
- previous_changes.include?(attr_name)
191
+ # Handle <tt>restore_*!</tt> for +method_missing+.
192
+ def restore_attribute!(attr)
193
+ if attribute_changed?(attr)
194
+ __send__("#{attr}=", changed_attributes[attr])
195
+ clear_attribute_changes([attr])
203
196
  end
197
+ end
198
+
199
+ # Returns +true+ if attr_name were changed before the model was saved,
200
+ # +false+ otherwise.
201
+ def previous_changes_include?(attr_name)
202
+ previous_changes.include?(attr_name)
203
+ end
204
204
 
205
- # This is necessary because `changed_attributes` might be overridden in
206
- # other implemntations (e.g. in `ActiveRecord`)
207
- alias_method :attributes_changed_by_setter, :changed_attributes # :nodoc:
205
+ # This is necessary because `changed_attributes` might be overridden in
206
+ # other implemntations (e.g. in `ActiveRecord`)
207
+ alias attributes_changed_by_setter changed_attributes # :nodoc:
208
208
 
209
- # Force an attribute to have a particular "before" value
210
- def set_attribute_was(attr, old_value)
211
- attributes_changed_by_setter[attr] = old_value
212
- end
209
+ # Force an attribute to have a particular "before" value
210
+ def set_attribute_was(attr, old_value)
211
+ attributes_changed_by_setter[attr] = old_value
212
+ end
213
213
 
214
- # Remove changes information for the provided attributes.
215
- def clear_attribute_changes(attributes) # :doc:
216
- attributes_changed_by_setter.except!(*attributes)
217
- end
214
+ # Remove changes information for the provided attributes.
215
+ def clear_attribute_changes(attributes) # :doc:
216
+ attributes_changed_by_setter.except!(*attributes)
217
+ end
218
218
  end
219
219
  end
@@ -51,7 +51,6 @@ module Dynamoid #:nodoc:
51
51
  options[:write_capacity] || Dynamoid::Config.write_capacity
52
52
  end
53
53
 
54
-
55
54
  # Returns the billing (capacity) mode for this table.
56
55
  # Could be either :provisioned or :on_demand
57
56
  def capacity_mode
@@ -225,3 +224,5 @@ module Dynamoid #:nodoc:
225
224
  end
226
225
  end
227
226
  end
227
+
228
+ ActiveSupport.run_load_hooks(:dynamoid, Dynamoid::Document)
@@ -55,6 +55,12 @@ module Dynamoid #:nodoc:
55
55
  end
56
56
  self.attributes = attributes.merge(name => { type: type }.merge(options))
57
57
 
58
+ # should be called before `define_attribute_methods` method because it defines a getter itself
59
+ warn_about_method_overriding(name, name)
60
+ warn_about_method_overriding("#{named}=", name)
61
+ warn_about_method_overriding("#{named}?", name)
62
+ warn_about_method_overriding("#{named}_before_type_cast?", name)
63
+
58
64
  define_attribute_method(name) # Dirty API
59
65
 
60
66
  generated_methods.module_eval do
@@ -127,6 +133,12 @@ module Dynamoid #:nodoc:
127
133
  end
128
134
  end
129
135
  end
136
+
137
+ def warn_about_method_overriding(method_name, field_name)
138
+ if self.instance_methods.include?(method_name.to_sym)
139
+ Dynamoid.logger.warn("Method #{method_name} generated for the field #{field_name} overrides already existing method")
140
+ end
141
+ end
130
142
  end
131
143
 
132
144
  # You can access the attributes of an object directly on its attributes method, which is by default an empty hash.
@@ -192,7 +204,8 @@ module Dynamoid #:nodoc:
192
204
  #
193
205
  # @since 0.2.0
194
206
  def set_updated_at
195
- if self.class.timestamps_enabled? && !updated_at_changed?
207
+ # @_touch_record=false means explicit disabling
208
+ if self.class.timestamps_enabled? && !updated_at_changed? && @_touch_record != false
196
209
  self.updated_at = DateTime.now.in_time_zone(Time.zone)
197
210
  end
198
211
  end
@@ -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)).flat_map{ |i| i }.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).flat_map{ |i| i }.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
@@ -267,9 +267,9 @@ module Dynamoid
267
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
- return chain.all
270
+ chain.all
271
271
  else
272
- return chain.first
272
+ chain.first
273
273
  end
274
274
  else
275
275
  super
@@ -165,8 +165,8 @@ module Dynamoid
165
165
  DEFAULT_PROJECTION_TYPE = :keys_only
166
166
 
167
167
  attr_accessor :name, :dynamoid_class, :type, :hash_key, :range_key,
168
- :hash_key_schema, :range_key_schema, :projected_attributes,
169
- :read_capacity, :write_capacity
168
+ :hash_key_schema, :range_key_schema, :projected_attributes,
169
+ :read_capacity, :write_capacity
170
170
 
171
171
  validate do
172
172
  validate_index_type
@@ -11,8 +11,8 @@ require 'dynamoid/persistence/save'
11
11
 
12
12
  # encoding: utf-8
13
13
  module Dynamoid
14
- # Persistence is responsible for dumping objects to and marshalling objects from the datastore. It tries to reserialize
15
- # values to be of the same type as when they were passed in, based on the fields in the class.
14
+ # # Persistence is responsible for dumping objects to and marshalling objects from the datastore. It tries to reserialize
15
+ # # values to be of the same type as when they were passed in, based on the fields in the class.
16
16
  module Persistence
17
17
  extend ActiveSupport::Concern
18
18
 
@@ -146,6 +146,25 @@ module Dynamoid
146
146
  model
147
147
  end
148
148
 
149
+ # Update document with provided attributes.
150
+ #
151
+ # Instantiates document and saves changes.
152
+ # Runs validations and callbacks. Raises Dynamoid::Errors::DocumentNotValid exception if validation fails.
153
+ #
154
+ # @param [Scalar value] partition key
155
+ # @param [Scalar value] sort key, optional
156
+ # @param [Hash] attributes
157
+ #
158
+ # @return [Dynamoid::Doument] updated document
159
+ #
160
+ # @example Update document
161
+ # Post.update!(101, title: 'New title')
162
+ def update!(hash_key, range_key_value = nil, attrs)
163
+ model = find(hash_key, range_key: range_key_value, consistent_read: true)
164
+ model.update_attributes!(attrs)
165
+ model
166
+ end
167
+
149
168
  # Update document.
150
169
  #
151
170
  # Uses efficient low-level `UpdateItem` API call.
@@ -264,14 +283,16 @@ module Dynamoid
264
283
  #
265
284
  # @since 0.2.0
266
285
  def persisted?
267
- !new_record?
286
+ !(new_record? || @destroyed)
268
287
  end
269
288
 
270
289
  # Run the callbacks and then persist this object in the datastore.
271
290
  #
272
291
  # @since 0.2.0
273
- def save(_options = {})
274
- self.class.create_table
292
+ def save(options = {})
293
+ self.class.create_table(sync: true)
294
+
295
+ @_touch_record = options[:touch]
275
296
 
276
297
  if new_record?
277
298
  run_callbacks(:create) do
@@ -342,7 +363,6 @@ module Dynamoid
342
363
  raise Dynamoid::Errors::StaleObjectError.new(self, 'update')
343
364
  end
344
365
  end
345
-
346
366
  end
347
367
 
348
368
  def update(conditions = {}, &block)
@@ -389,6 +409,9 @@ module Dynamoid
389
409
  ret = run_callbacks(:destroy) do
390
410
  delete
391
411
  end
412
+
413
+ @destroyed = true
414
+
392
415
  ret == false ? false : self
393
416
  end
394
417
 
@@ -413,6 +436,9 @@ module Dynamoid
413
436
  end
414
437
  options[:conditions] = conditions
415
438
  end
439
+
440
+ @destroyed = true
441
+
416
442
  Dynamoid.adapter.delete(self.class.table_name, hash_key, options)
417
443
  rescue Dynamoid::Errors::ConditionalCheckFailedException
418
444
  raise Dynamoid::Errors::StaleObjectError.new(self, 'delete')
@@ -57,4 +57,3 @@ module Dynamoid
57
57
  end
58
58
  end
59
59
  end
60
-
@@ -1 +1,3 @@
1
- load "dynamoid/tasks/database.rake"
1
+ # frozen_string_literal: true
2
+
3
+ load 'dynamoid/tasks/database.rake'
@@ -215,8 +215,6 @@ module Dynamoid
215
215
  value.to_hash
216
216
  elsif value.respond_to? :to_h
217
217
  value.to_h
218
- else
219
- nil
220
218
  end
221
219
  end
222
220
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dynamoid
4
- VERSION = '3.4.1'
4
+ VERSION = '3.5.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.4.1
4
+ version: 3.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josh Symonds
@@ -19,9 +19,9 @@ authors:
19
19
  - Peter Boling
20
20
  - Andrew Konchin
21
21
  autorequire:
22
- bindir: exe
22
+ bindir: bin
23
23
  cert_chain: []
24
- date: 2019-12-02 00:00:00.000000000 Z
24
+ date: 2020-04-04 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
@@ -83,16 +83,16 @@ dependencies:
83
83
  name: appraisal
84
84
  requirement: !ruby/object:Gem::Requirement
85
85
  requirements:
86
- - - ">="
86
+ - - "~>"
87
87
  - !ruby/object:Gem::Version
88
- version: '0'
88
+ version: '2.2'
89
89
  type: :development
90
90
  prerelease: false
91
91
  version_requirements: !ruby/object:Gem::Requirement
92
92
  requirements:
93
- - - ">="
93
+ - - "~>"
94
94
  - !ruby/object:Gem::Version
95
- version: '0'
95
+ version: '2.2'
96
96
  - !ruby/object:Gem::Dependency
97
97
  name: bundler
98
98
  requirement: !ruby/object:Gem::Requirement
@@ -111,58 +111,58 @@ dependencies:
111
111
  name: coveralls
112
112
  requirement: !ruby/object:Gem::Requirement
113
113
  requirements:
114
- - - ">="
114
+ - - "~>"
115
115
  - !ruby/object:Gem::Version
116
- version: '0'
116
+ version: '0.8'
117
117
  type: :development
118
118
  prerelease: false
119
119
  version_requirements: !ruby/object:Gem::Requirement
120
120
  requirements:
121
- - - ">="
121
+ - - "~>"
122
122
  - !ruby/object:Gem::Version
123
- version: '0'
123
+ version: '0.8'
124
124
  - !ruby/object:Gem::Dependency
125
125
  name: pry
126
126
  requirement: !ruby/object:Gem::Requirement
127
127
  requirements:
128
- - - ">="
128
+ - - "~>"
129
129
  - !ruby/object:Gem::Version
130
- version: '0'
130
+ version: 0.12.0
131
131
  type: :development
132
132
  prerelease: false
133
133
  version_requirements: !ruby/object:Gem::Requirement
134
134
  requirements:
135
- - - ">="
135
+ - - "~>"
136
136
  - !ruby/object:Gem::Version
137
- version: '0'
137
+ version: 0.12.0
138
138
  - !ruby/object:Gem::Dependency
139
139
  name: rake
140
140
  requirement: !ruby/object:Gem::Requirement
141
141
  requirements:
142
- - - ">="
142
+ - - "~>"
143
143
  - !ruby/object:Gem::Version
144
- version: '0'
144
+ version: '13.0'
145
145
  type: :development
146
146
  prerelease: false
147
147
  version_requirements: !ruby/object:Gem::Requirement
148
148
  requirements:
149
- - - ">="
149
+ - - "~>"
150
150
  - !ruby/object:Gem::Version
151
- version: '0'
151
+ version: '13.0'
152
152
  - !ruby/object:Gem::Dependency
153
153
  name: rspec
154
154
  requirement: !ruby/object:Gem::Requirement
155
155
  requirements:
156
- - - ">="
156
+ - - "~>"
157
157
  - !ruby/object:Gem::Version
158
- version: '0'
158
+ version: '3.9'
159
159
  type: :development
160
160
  prerelease: false
161
161
  version_requirements: !ruby/object:Gem::Requirement
162
162
  requirements:
163
- - - ">="
163
+ - - "~>"
164
164
  - !ruby/object:Gem::Version
165
- version: '0'
165
+ version: '3.9'
166
166
  - !ruby/object:Gem::Dependency
167
167
  name: rubocop
168
168
  requirement: !ruby/object:Gem::Requirement
@@ -181,63 +181,44 @@ dependencies:
181
181
  name: wwtd
182
182
  requirement: !ruby/object:Gem::Requirement
183
183
  requirements:
184
- - - ">="
184
+ - - "~>"
185
185
  - !ruby/object:Gem::Version
186
- version: '0'
186
+ version: '1.4'
187
187
  type: :development
188
188
  prerelease: false
189
189
  version_requirements: !ruby/object:Gem::Requirement
190
190
  requirements:
191
- - - ">="
191
+ - - "~>"
192
192
  - !ruby/object:Gem::Version
193
- version: '0'
193
+ version: '1.4'
194
194
  - !ruby/object:Gem::Dependency
195
195
  name: yard
196
196
  requirement: !ruby/object:Gem::Requirement
197
197
  requirements:
198
- - - ">="
198
+ - - "~>"
199
199
  - !ruby/object:Gem::Version
200
- version: '0'
200
+ version: '0.9'
201
201
  type: :development
202
202
  prerelease: false
203
203
  version_requirements: !ruby/object:Gem::Requirement
204
204
  requirements:
205
- - - ">="
205
+ - - "~>"
206
206
  - !ruby/object:Gem::Version
207
- version: '0'
207
+ version: '0.9'
208
208
  description: Dynamoid is an ORM for Amazon's DynamoDB that supports offline development,
209
209
  associations, querying, and everything else you'd expect from an ActiveRecord-style
210
210
  replacement.
211
211
  email:
212
212
  - peter.boling@gmail.com
213
213
  - brian@stellaservice.com
214
+ - andry.konchin@gmail.com
214
215
  executables: []
215
216
  extensions: []
216
- extra_rdoc_files:
217
- - LICENSE.txt
218
- - README.md
217
+ extra_rdoc_files: []
219
218
  files:
220
- - ".coveralls.yml"
221
- - ".document"
222
- - ".gitignore"
223
- - ".rspec"
224
- - ".rubocop.yml"
225
- - ".rubocop_todo.yml"
226
- - ".travis.yml"
227
- - Appraisals
228
219
  - CHANGELOG.md
229
- - Gemfile
230
220
  - LICENSE.txt
231
221
  - 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
222
  - lib/dynamoid.rb
242
223
  - lib/dynamoid/adapter.rb
243
224
  - lib/dynamoid/adapter_plugin/aws_sdk_v3.rb
@@ -296,10 +277,13 @@ files:
296
277
  - lib/dynamoid/undumping.rb
297
278
  - lib/dynamoid/validations.rb
298
279
  - lib/dynamoid/version.rb
299
- homepage: http://github.com/Dynamoid/Dynamoid
280
+ homepage: http://github.com/Dynamoid/dynamoid
300
281
  licenses:
301
282
  - MIT
302
- metadata: {}
283
+ metadata:
284
+ bug_tracker_uri: https://github.com/Dynamoid/dynamoid/issues
285
+ changelog_uri: https://github.com/Dynamoid/dynamoid/tag/v3.5.0/CHANGELOG.md
286
+ source_code_uri: https://github.com/Dynamoid/dynamoid/tree/v3.5.0
303
287
  post_install_message:
304
288
  rdoc_options: []
305
289
  require_paths: