dynamoid 3.7.0 → 3.8.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.
data/LICENSE.txt CHANGED
@@ -1,7 +1,7 @@
1
- MIT License
1
+ The MIT License (MIT)
2
2
 
3
3
  Copyright (c) 2012 Josh Symonds
4
- Copyright (c) 2013 - 2018 Dynamoid, https://github.com/Dynamoid
4
+ Copyright (c) 2013 - 2022 Dynamoid, https://github.com/Dynamoid
5
5
 
6
6
  Permission is hereby granted, free of charge, to any person obtaining a copy
7
7
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,12 +1,21 @@
1
1
  # Dynamoid
2
2
 
3
- [![Build Status](https://travis-ci.org/Dynamoid/dynamoid.svg?branch=master)](https://travis-ci.org/Dynamoid/dynamoid)
3
+ [![Build Status](https://github.com/Dynamoid/dynamoid/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/Dynamoid/dynamoid/actions/workflows/ci.yml/badge.svg?branch=master)
4
4
  [![Code Climate](https://codeclimate.com/github/Dynamoid/dynamoid.svg)](https://codeclimate.com/github/Dynamoid/dynamoid)
5
5
  [![Coverage Status](https://coveralls.io/repos/github/Dynamoid/dynamoid/badge.svg?branch=master)](https://coveralls.io/github/Dynamoid/dynamoid?branch=master)
6
6
  [![CodeTriage Helpers](https://www.codetriage.com/dynamoid/dynamoid/badges/users.svg)](https://www.codetriage.com/dynamoid/dynamoid)
7
7
  [![Yard Docs](http://img.shields.io/badge/yard-docs-blue.svg)](https://www.rubydoc.info/github/Dynamoid/dynamoid/frames)
8
8
  [![Inline docs](http://inch-ci.org/github/Dynamoid/Dynamoid.svg?branch=master)](http://inch-ci.org/github/Dynamoid/Dynamoid)
9
9
  ![GitHub](https://img.shields.io/github/license/Dynamoid/dynamoid.svg)
10
+ [![GitMoji][🖐gitmoji-img]][🖐gitmoji]
11
+ [![SemVer 2.0.0][🧮semver-img]][semver]
12
+ [![Keep-A-Changelog 1.0.0][📗keep-changelog-img]][📗keep-changelog]
13
+
14
+ [🖐gitmoji]: https://gitmoji.dev
15
+ [🖐gitmoji-img]: https://img.shields.io/badge/gitmoji-3.9.0-FFDD67.svg?style=flat
16
+ [🧮semver-img]: https://img.shields.io/badge/semver-2.0.0-FFDD67.svg?style=flat
17
+ [📗keep-changelog]: https://keepachangelog.com/en/1.0.0/
18
+ [📗keep-changelog-img]: https://img.shields.io/badge/keep--a--changelog-1.0.0-FFDD67.svg?style=flat
10
19
 
11
20
  Dynamoid is an ORM for Amazon's DynamoDB for Ruby applications. It
12
21
  provides similar functionality to ActiveRecord and improves on Amazon's
@@ -127,7 +136,7 @@ Dynamoid supports Ruby >= 2.3 and Rails >= 4.2.
127
136
 
128
137
  Its compatibility is tested against following Ruby versions: 2.3, 2.4,
129
138
  2.5, 2.6, 2.7 and 3.0, JRuby 9.2.x and against Rails versions: 4.2, 5.0, 5.1,
130
- 5.2, 6.0 and 6.1.
139
+ 5.2, 6.0, 6.1 and 7.0.
131
140
 
132
141
  ## Setup
133
142
 
@@ -468,6 +477,10 @@ Second argument, type, is optional. Default type is `string`.
468
477
  Just like in ActiveRecord (or your other favorite ORM), Dynamoid uses
469
478
  associations to create links between models.
470
479
 
480
+ **WARNING:** Associations are not supported for models with compound
481
+ primary key. If a model declares a range key it should not declare any
482
+ association itself and be referenced by an association in another model.
483
+
471
484
  The only supported associations (so far) are `has_many`, `has_one`,
472
485
  `has_and_belongs_to_many`, and `belongs_to`. Associations are very
473
486
  simple to create: just specify the type, the name, and then any options
@@ -1073,7 +1086,7 @@ Listed below are all configuration options.
1073
1086
  when referring to them. Isn't thread safe. Default is `false`.
1074
1087
  `Use Dynamoid::Middleware::IdentityMap` to clear identity map for each HTTP request
1075
1088
  * `timestamps` - by default Dynamoid sets `created_at` and `updated_at`
1076
- fields for model creation and updating. You can disable this
1089
+ fields at model creation and updating. You can disable this
1077
1090
  behavior by setting `false` value
1078
1091
  * `sync_retry_max_times` - when Dynamoid creates or deletes table
1079
1092
  synchronously it checks for completion specified times. Default is 60
@@ -1335,7 +1348,7 @@ DynamoDB running locally. Follow these steps to setup your test
1335
1348
  environment.
1336
1349
 
1337
1350
  * First download and unpack the latest version of DynamoDB. We have a
1338
- script that will do this for you if you use homebrew on a Mac.
1351
+ script that will do this for you if you use bash, and homebrew on a Mac.
1339
1352
 
1340
1353
  ```shell
1341
1354
  bin/setup
@@ -1360,25 +1373,37 @@ environment.
1360
1373
  bin/stop_dynamodblocal
1361
1374
  ```
1362
1375
 
1363
- If you want to run all the specs that travis runs, use `bundle exec
1364
- wwtd`, but first you will need to setup all the rubies, for each of `%w(
1365
- 2.3.8 2.4.6 2.5.5 2.6.3 2.7.0 3.0.0 9.2.14.0)`. When you run
1366
- `bundle exec wwtd` it will take care of starting and stopping the local
1367
- dynamodb instance.
1368
-
1376
+ If you run into issues, please try these steps first.
1377
+ NOTE: You can use any version manager: rvm, rbenv, chruby, asdf-ruby
1369
1378
  ```shell
1370
- rvm use 3.0.0
1371
- gem install rubygems-update
1372
- gem install bundler
1379
+ asdf install ruby 3.1.1
1380
+ asdf local ruby 3.1.1
1381
+ gem update --system
1373
1382
  bundle install
1374
1383
  ```
1375
1384
 
1376
- ## Copyright
1385
+ ## Security
1386
+
1387
+ See [SECURITY.md][security].
1388
+
1389
+ ## Related links
1390
+
1391
+ This documentation may be useful for the contributors:
1392
+ - <https://docs.aws.amazon.com/sdk-for-ruby/v3/developer-guide/welcome.html>
1393
+ - <https://docs.aws.amazon.com/sdk-for-ruby/v3/api/index.html>
1394
+
1395
+ ## License
1396
+
1397
+ The gem is available as open source under the terms of
1398
+ the [MIT License][license] [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)][license-ref].
1399
+ See [LICENSE][license] for the official [Copyright Notice][copyright-notice-explainer].
1400
+
1401
+ [copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
1377
1402
 
1378
- Copyright (c) 2012 Josh Symonds.
1403
+ [license]: https://github.com/Dynamoid/dynamoid/blob/master/LICENSE.txt
1379
1404
 
1380
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
1405
+ [license-ref]: https://opensource.org/licenses/MIT
1381
1406
 
1382
- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
1407
+ [security]: https://github.com/Dynamoid/dynamoid/blob/master/SECURITY.md
1383
1408
 
1384
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1409
+ [semver]: http://semver.org/
@@ -1,11 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # require only 'concurrent/atom' once this issue is resolved:
4
- # https://github.com/ruby-concurrency/concurrent-ruby/pull/377
5
- require 'concurrent'
3
+ require 'concurrent/atom'
6
4
  require 'dynamoid/adapter_plugin/aws_sdk_v3'
7
5
 
8
- # encoding: utf-8
9
6
  module Dynamoid
10
7
  # Adapter's value-add:
11
8
  # 1) For the rest of Dynamoid, the gateway to DynamoDB.
@@ -44,7 +41,7 @@ module Dynamoid
44
41
 
45
42
  # Shows how long it takes a method to run on the adapter. Useful for generating logged output.
46
43
  #
47
- # @param [Symbol] method the name of the method to appear in the log
44
+ # @param [Symbol|String] method the name of the method to appear in the log
48
45
  # @param [Array] args the arguments to the method to appear in the log
49
46
  # @yield the actual code to benchmark
50
47
  #
@@ -78,7 +75,7 @@ module Dynamoid
78
75
  # that the batch get will acquire the correct record.
79
76
  #
80
77
  # @param [String] table the name of the table to write the object to
81
- # @param [Array] ids to fetch, can also be a string of just one id
78
+ # @param [String, Array] ids to fetch; can also be a string of just one id
82
79
  # @param [Hash] options Passed to the underlying query. The :range_key option is required whenever the table has a range key,
83
80
  # unless multiple ids are passed in.
84
81
  #
@@ -94,7 +91,7 @@ module Dynamoid
94
91
  # Delete an item from a table.
95
92
  #
96
93
  # @param [String] table the name of the table to write the object to
97
- # @param [Array] ids to delete, can also be a string of just one id
94
+ # @param [String, Array] ids to delete; can also be a string of just one id
98
95
  # @param [Hash] options allowed only +range_key+ - range key or array of
99
96
  # range keys of the record to delete, can also be
100
97
  # a string of just one range_key, and +conditions+
@@ -150,7 +147,7 @@ module Dynamoid
150
147
  #
151
148
  # @since 0.2.0
152
149
  define_method(m) do |*args, &blk|
153
- benchmark(m.to_s, *args) { adapter.send(m, *args, &blk) }
150
+ benchmark(m, *args) { adapter.send(m, *args, &blk) }
154
151
  end
155
152
  end
156
153
 
@@ -86,7 +86,16 @@ module Dynamoid
86
86
  def unprocessed_ids(table)
87
87
  # unprocessed_keys Hash contains as values instances of
88
88
  # Aws::DynamoDB::Types::KeysAndAttributes
89
- @api_response.unprocessed_keys[table.name].keys.map { |h| h[table.hash_key.to_s] }
89
+ @api_response.unprocessed_keys[table.name].keys.map do |h|
90
+ # If a table has a composite primary key then we need to return an array
91
+ # of [hash key, range key]. Otherwise just return hash key's
92
+ # value.
93
+ if table.range_key.nil?
94
+ h[table.hash_key.to_s]
95
+ else
96
+ [h[table.hash_key.to_s], h[table.range_key.to_s]]
97
+ end
98
+ end
90
99
  end
91
100
 
92
101
  def items_grouped_by_table
@@ -6,6 +6,10 @@ module Dynamoid
6
6
  class AwsSdkV3
7
7
  # Mimics behavior of the yielded object on DynamoDB's update_item API (high level).
8
8
  class ItemUpdater
9
+ ADD = 'ADD'
10
+ DELETE = 'DELETE'
11
+ PUT = 'PUT'
12
+
9
13
  attr_reader :table, :key, :range_key
10
14
 
11
15
  def initialize(table, key, range_key = nil)
@@ -31,11 +35,15 @@ module Dynamoid
31
35
  #
32
36
  # Removes values from the sets of the given columns
33
37
  #
34
- # @param [Hash] values keys of the hash are the columns, values are Arrays/Sets of items
35
- # to remove
38
+ # @param [Hash|Symbol|String] values keys of the hash are the columns, values are Arrays/Sets of items
39
+ # to remove
36
40
  #
37
41
  def delete(values)
38
- @deletions.merge!(sanitize_attributes(values))
42
+ if values.is_a?(Hash)
43
+ @deletions.merge!(sanitize_attributes(values))
44
+ else
45
+ @deletions.merge!(values.to_s => nil)
46
+ end
39
47
  end
40
48
 
41
49
  #
@@ -48,29 +56,31 @@ module Dynamoid
48
56
  #
49
57
  # Returns an AttributeUpdates hash suitable for passing to the V2 Client API
50
58
  #
51
- def to_h
52
- ret = {}
59
+ def attribute_updates
60
+ result = {}
53
61
 
54
62
  @additions.each do |k, v|
55
- ret[k.to_s] = {
63
+ result[k] = {
56
64
  action: ADD,
57
65
  value: v
58
66
  }
59
67
  end
68
+
60
69
  @deletions.each do |k, v|
61
- ret[k.to_s] = {
70
+ result[k] = {
62
71
  action: DELETE
63
72
  }
64
- ret[k.to_s][:value] = v unless v.nil?
73
+ result[k][:value] = v unless v.nil?
65
74
  end
75
+
66
76
  @updates.each do |k, v|
67
- ret[k.to_s] = {
77
+ result[k] = {
68
78
  action: PUT,
69
79
  value: v
70
80
  }
71
81
  end
72
82
 
73
- ret
83
+ result
74
84
  end
75
85
 
76
86
  private
@@ -80,10 +90,6 @@ module Dynamoid
80
90
  v.is_a?(Hash) ? v.stringify_keys : v
81
91
  end
82
92
  end
83
-
84
- ADD = 'ADD'
85
- DELETE = 'DELETE'
86
- PUT = 'PUT'
87
93
  end
88
94
  end
89
95
  end
@@ -48,7 +48,8 @@ module Dynamoid
48
48
  request = options.slice(
49
49
  :consistent_read,
50
50
  :exclusive_start_key,
51
- :select
51
+ :select,
52
+ :index_name
52
53
  ).compact
53
54
 
54
55
  # Deal with various limits and batching
@@ -163,30 +163,28 @@ module Dynamoid
163
163
  def batch_write_item(table_name, objects, options = {})
164
164
  items = objects.map { |o| sanitize_item(o) }
165
165
 
166
- begin
167
- while items.present?
168
- batch = items.shift(BATCH_WRITE_ITEM_REQUESTS_LIMIT)
169
- requests = batch.map { |item| { put_request: { item: item } } }
170
-
171
- response = client.batch_write_item(
172
- {
173
- request_items: {
174
- table_name => requests
175
- },
176
- return_consumed_capacity: 'TOTAL',
177
- return_item_collection_metrics: 'SIZE'
178
- }.merge!(options)
179
- )
166
+ while items.present?
167
+ batch = items.shift(BATCH_WRITE_ITEM_REQUESTS_LIMIT)
168
+ requests = batch.map { |item| { put_request: { item: item } } }
180
169
 
181
- yield(response.unprocessed_items.present?) if block_given?
170
+ response = client.batch_write_item(
171
+ {
172
+ request_items: {
173
+ table_name => requests
174
+ },
175
+ return_consumed_capacity: 'TOTAL',
176
+ return_item_collection_metrics: 'SIZE'
177
+ }.merge!(options)
178
+ )
182
179
 
183
- if response.unprocessed_items.present?
184
- items += response.unprocessed_items[table_name].map { |r| r.put_request.item }
185
- end
180
+ yield(response.unprocessed_items.present?) if block_given?
181
+
182
+ if response.unprocessed_items.present?
183
+ items += response.unprocessed_items[table_name].map { |r| r.put_request.item }
186
184
  end
187
- rescue Aws::DynamoDB::Errors::ConditionalCheckFailedException => e
188
- raise Dynamoid::Errors::ConditionalCheckFailedException, e
189
185
  end
186
+ rescue Aws::DynamoDB::Errors::ConditionalCheckFailedException => e
187
+ raise Dynamoid::Errors::ConditionalCheckFailedException, e
190
188
  end
191
189
 
192
190
  # Get many items at once from DynamoDB. More efficient than getting each item individually.
@@ -258,17 +256,15 @@ module Dynamoid
258
256
  end
259
257
  end
260
258
 
261
- begin
262
- requests.map do |request_items|
263
- client.batch_write_item(
264
- request_items: request_items,
265
- return_consumed_capacity: 'TOTAL',
266
- return_item_collection_metrics: 'SIZE'
267
- )
268
- end
269
- rescue Aws::DynamoDB::Errors::ConditionalCheckFailedException => e
270
- raise Dynamoid::Errors::ConditionalCheckFailedException, e
259
+ requests.each do |items|
260
+ client.batch_write_item(
261
+ request_items: items,
262
+ return_consumed_capacity: 'TOTAL',
263
+ return_item_collection_metrics: 'SIZE'
264
+ )
271
265
  end
266
+ rescue Aws::DynamoDB::Errors::ConditionalCheckFailedException => e
267
+ raise Dynamoid::Errors::ConditionalCheckFailedException, e
272
268
  end
273
269
 
274
270
  # Create a table on DynamoDB. This usually takes a long time to complete.
@@ -416,20 +412,19 @@ module Dynamoid
416
412
  conditions = options.delete(:conditions)
417
413
  table = describe_table(table_name)
418
414
 
419
- yield(iu = ItemUpdater.new(table, key, range_key))
415
+ item_updater = ItemUpdater.new(table, key, range_key)
416
+ yield(item_updater)
420
417
 
421
418
  raise "non-empty options: #{options}" unless options.empty?
422
419
 
423
- begin
424
- result = client.update_item(table_name: table_name,
425
- key: key_stanza(table, key, range_key),
426
- attribute_updates: iu.to_h,
427
- expected: expected_stanza(conditions),
428
- return_values: 'ALL_NEW')
429
- result_item_to_hash(result[:attributes])
430
- rescue Aws::DynamoDB::Errors::ConditionalCheckFailedException => e
431
- raise Dynamoid::Errors::ConditionalCheckFailedException, e
432
- end
420
+ result = client.update_item(table_name: table_name,
421
+ key: key_stanza(table, key, range_key),
422
+ attribute_updates: item_updater.attribute_updates,
423
+ expected: expected_stanza(conditions),
424
+ return_values: 'ALL_NEW')
425
+ result_item_to_hash(result[:attributes])
426
+ rescue Aws::DynamoDB::Errors::ConditionalCheckFailedException => e
427
+ raise Dynamoid::Errors::ConditionalCheckFailedException, e
433
428
  end
434
429
 
435
430
  # List all tables on DynamoDB.
@@ -459,17 +454,15 @@ module Dynamoid
459
454
  options ||= {}
460
455
  item = sanitize_item(object)
461
456
 
462
- begin
463
- client.put_item(
464
- {
465
- table_name: table_name,
466
- item: item,
467
- expected: expected_stanza(options)
468
- }.merge!(options)
469
- )
470
- rescue Aws::DynamoDB::Errors::ConditionalCheckFailedException => e
471
- raise Dynamoid::Errors::ConditionalCheckFailedException, e
472
- end
457
+ client.put_item(
458
+ {
459
+ table_name: table_name,
460
+ item: item,
461
+ expected: expected_stanza(options)
462
+ }.merge!(options)
463
+ )
464
+ rescue Aws::DynamoDB::Errors::ConditionalCheckFailedException => e
465
+ raise Dynamoid::Errors::ConditionalCheckFailedException, e
473
466
  end
474
467
 
475
468
  # Query the DynamoDB table. This employs DynamoDB's indexes so is generally faster than scanning, but is
@@ -64,18 +64,37 @@ module Dynamoid
64
64
  target == other
65
65
  end
66
66
 
67
- # Delegate methods we don't find directly to the target.
68
- #
69
- # @private
70
- # @since 0.2.0
71
- def method_missing(method, *args)
72
- if target.respond_to?(method)
73
- target.send(method, *args)
74
- else
75
- super
67
+ if ::RUBY_VERSION < '2.7'
68
+ # Delegate methods we don't find directly to the target.
69
+ #
70
+ # @private
71
+ # @since 0.2.0
72
+ def method_missing(method, *args, &block)
73
+ if target.respond_to?(method)
74
+ target.send(method, *args, &block)
75
+ else
76
+ super
77
+ end
78
+ end
79
+ else
80
+ # Delegate methods we don't find directly to the target.
81
+ #
82
+ # @private
83
+ # @since 0.2.0
84
+ def method_missing(method, *args, **kwargs, &block)
85
+ if target.respond_to?(method)
86
+ target.send(method, *args, **kwargs, &block)
87
+ else
88
+ super
89
+ end
76
90
  end
77
91
  end
78
92
 
93
+ # @private
94
+ def respond_to_missing?(method_name, include_private = false)
95
+ target.respond_to?(method_name, include_private) || super
96
+ end
97
+
79
98
  # @private
80
99
  def nil?
81
100
  target.nil?
@@ -187,10 +187,10 @@ module Dynamoid
187
187
  def first(*args)
188
188
  n = args.first || 1
189
189
 
190
- return scan_limit(n).to_a.first(*args) if @query.blank?
190
+ return self.dup.scan_limit(n).to_a.first(*args) if @query.blank?
191
191
  return super if @key_fields_detector.non_key_present?
192
192
 
193
- record_limit(n).to_a.first(*args)
193
+ self.dup.record_limit(n).to_a.first(*args)
194
194
  end
195
195
 
196
196
  # Returns the last item matching the criteria.
@@ -486,15 +486,17 @@ module Dynamoid
486
486
  # @return [Array]
487
487
  def pluck(*args)
488
488
  fields = args.map(&:to_sym)
489
- @project = fields
489
+
490
+ scope = self.dup
491
+ scope.project(*fields)
490
492
 
491
493
  if fields.many?
492
- items.map do |item|
494
+ scope.items.map do |item|
493
495
  fields.map { |key| Undumping.undump_field(item[key], source.attributes[key]) }
494
496
  end.to_a
495
497
  else
496
498
  key = fields.first
497
- items.map { |item| Undumping.undump_field(item[key], source.attributes[key]) }.to_a
499
+ scope.items.map { |item| Undumping.undump_field(item[key], source.attributes[key]) }.to_a
498
500
  end
499
501
  end
500
502
 
@@ -513,6 +515,7 @@ module Dynamoid
513
515
  def items
514
516
  raw_pages.lazy.flat_map { |items, _| items }
515
517
  end
518
+ protected :items
516
519
 
517
520
  # Arrays of records, sized based on the actual pages produced by DynamoDB
518
521
  #
@@ -568,7 +571,7 @@ module Dynamoid
568
571
 
569
572
  def issue_scan_warning
570
573
  Dynamoid.logger.warn 'Queries without an index are forced to use scan and are generally much slower than indexed queries!'
571
- Dynamoid.logger.warn "You can index this query by adding index declaration to #{source.to_s.downcase}.rb:"
574
+ Dynamoid.logger.warn "You can index this query by adding index declaration to #{source.to_s.underscore}.rb:"
572
575
  Dynamoid.logger.warn "* global_secondary_index hash_key: 'some-name', range_key: 'some-another-name'"
573
576
  Dynamoid.logger.warn "* local_secondary_index range_key: 'some-name'"
574
577
  Dynamoid.logger.warn "Not indexed attributes: #{query.keys.sort.collect { |name| ":#{name}" }.join(', ')}"
@@ -770,6 +773,7 @@ module Dynamoid
770
773
 
771
774
  def scan_opts
772
775
  opts = {}
776
+ opts[:index_name] = @key_fields_detector.index_name if @key_fields_detector.index_name
773
777
  opts[:record_limit] = @record_limit if @record_limit
774
778
  opts[:scan_limit] = @scan_limit if @scan_limit
775
779
  opts[:batch_size] = @batch_size if @batch_size
@@ -37,7 +37,7 @@ module Dynamoid
37
37
  end
38
38
 
39
39
  def key_present?
40
- @result.present?
40
+ @result.present? && @query.contain_with_eq_operator?(hash_key)
41
41
  end
42
42
 
43
43
  def hash_key
@@ -9,12 +9,15 @@ module Dynamoid
9
9
 
10
10
  # @private
11
11
  module ClassMethods
12
- %i[where consistent all first last delete_all destroy_all each record_limit scan_limit batch start scan_index_forward find_by_pages project pluck].each do |meth|
12
+ %i[
13
+ where consistent all first last delete_all destroy_all each record_limit
14
+ scan_limit batch start scan_index_forward find_by_pages project pluck
15
+ ].each do |name|
13
16
  # Return a criteria chain in response to a method that will begin or end a chain. For more information,
14
17
  # see Dynamoid::Criteria::Chain.
15
18
  #
16
19
  # @since 0.2.0
17
- define_method(meth) do |*args, &blk|
20
+ define_method(name) do |*args, &blk|
18
21
  # Don't use keywork arguments delegating (with **kw). It works in
19
22
  # different way in different Ruby versions: <= 2.6, 2.7, 3.0 and in some
20
23
  # future 3.x versions. Providing that there are no downstream methods
@@ -23,11 +26,7 @@ module Dynamoid
23
26
  # https://eregon.me/blog/2019/11/10/the-delegation-challenge-of-ruby27.html
24
27
 
25
28
  chain = Dynamoid::Criteria::Chain.new(self)
26
- if args
27
- chain.send(meth, *args, &blk)
28
- else
29
- chain.send(meth, &blk)
30
- end
29
+ chain.send(name, *args, &blk)
31
30
  end
32
31
  end
33
32
  end
@@ -25,17 +25,15 @@ module Dynamoid
25
25
  # @private
26
26
  module ClassMethods
27
27
  def update_fields(*)
28
- if model = super
29
- model.send(:clear_changes_information)
28
+ super.tap do |model|
29
+ model.send(:clear_changes_information) if model
30
30
  end
31
- model
32
31
  end
33
32
 
34
33
  def upsert(*)
35
- if model = super
36
- model.send(:clear_changes_information)
34
+ super.tap do |model|
35
+ model.send(:clear_changes_information) if model
37
36
  end
38
- model
39
37
  end
40
38
 
41
39
  def from_database(*)
@@ -47,10 +45,9 @@ module Dynamoid
47
45
 
48
46
  # @private
49
47
  def save(*)
50
- if status = super
51
- changes_applied
48
+ super.tap do |status|
49
+ changes_applied if status
52
50
  end
53
- status
54
51
  end
55
52
 
56
53
  # @private
@@ -17,12 +17,6 @@ module Dynamoid
17
17
  end
18
18
 
19
19
  module ClassMethods
20
- # @private
21
- def table(options = {})
22
- self.options = options
23
- super if defined? super
24
- end
25
-
26
20
  def attr_readonly(*read_only_attributes)
27
21
  self.read_only_attributes.concat read_only_attributes.map(&:to_s)
28
22
  end
@@ -77,10 +71,10 @@ module Dynamoid
77
71
 
78
72
  # Return the count of items for this class.
79
73
  #
80
- # It returns aproximate value based on DynamoDB statistic. DynamoDB
81
- # updates it periodicaly so the value can be no accurate.
74
+ # It returns approximate value based on DynamoDB statistic. DynamoDB
75
+ # updates it periodically so the value can be no accurate.
82
76
  #
83
- # It's a reletivly cheap operation and doesn't read all the items in a
77
+ # It's a reletively cheap operation and doesn't read all the items in a
84
78
  # table. It makes just one HTTP request to DynamoDB.
85
79
  #
86
80
  # @return [Integer] items count in a table
@@ -220,7 +214,7 @@ module Dynamoid
220
214
  # Check equality of two models.
221
215
  #
222
216
  # A model is equal to another model only if their primary keys (hash key
223
- # and optionaly range key) are equal.
217
+ # and optionally range key) are equal.
224
218
  #
225
219
  # @return [true|false]
226
220
  # @since 0.2.0