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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +35 -4
- data/README.md +24 -18
- data/lib/dynamoid.rb +1 -0
- data/lib/dynamoid/adapter.rb +7 -4
- data/lib/dynamoid/adapter_plugin/aws_sdk_v3.rb +14 -11
- data/lib/dynamoid/adapter_plugin/aws_sdk_v3/batch_get_item.rb +1 -0
- data/lib/dynamoid/adapter_plugin/aws_sdk_v3/create_table.rb +8 -7
- data/lib/dynamoid/adapter_plugin/aws_sdk_v3/item_updater.rb +3 -2
- data/lib/dynamoid/adapter_plugin/aws_sdk_v3/middleware/backoff.rb +1 -0
- data/lib/dynamoid/adapter_plugin/aws_sdk_v3/middleware/limit.rb +1 -0
- data/lib/dynamoid/adapter_plugin/aws_sdk_v3/middleware/start_key.rb +1 -0
- data/lib/dynamoid/adapter_plugin/aws_sdk_v3/query.rb +1 -0
- data/lib/dynamoid/adapter_plugin/aws_sdk_v3/scan.rb +1 -0
- data/lib/dynamoid/adapter_plugin/aws_sdk_v3/table.rb +1 -0
- data/lib/dynamoid/adapter_plugin/aws_sdk_v3/until_past_table_status.rb +1 -0
- data/lib/dynamoid/application_time_zone.rb +1 -0
- data/lib/dynamoid/associations.rb +182 -19
- data/lib/dynamoid/associations/association.rb +4 -2
- data/lib/dynamoid/associations/belongs_to.rb +2 -1
- data/lib/dynamoid/associations/has_and_belongs_to_many.rb +2 -1
- data/lib/dynamoid/associations/has_many.rb +2 -1
- data/lib/dynamoid/associations/has_one.rb +2 -1
- data/lib/dynamoid/associations/many_association.rb +65 -22
- data/lib/dynamoid/associations/single_association.rb +28 -1
- data/lib/dynamoid/components.rb +1 -0
- data/lib/dynamoid/config.rb +3 -2
- data/lib/dynamoid/config/backoff_strategies/constant_backoff.rb +1 -0
- data/lib/dynamoid/config/backoff_strategies/exponential_backoff.rb +1 -0
- data/lib/dynamoid/config/options.rb +1 -0
- data/lib/dynamoid/criteria.rb +1 -0
- data/lib/dynamoid/criteria/chain.rb +353 -33
- data/lib/dynamoid/criteria/ignored_conditions_detector.rb +1 -0
- data/lib/dynamoid/criteria/key_fields_detector.rb +10 -1
- data/lib/dynamoid/criteria/nonexistent_fields_detector.rb +1 -0
- data/lib/dynamoid/criteria/overwritten_conditions_detector.rb +1 -0
- data/lib/dynamoid/dirty.rb +71 -16
- data/lib/dynamoid/document.rb +123 -42
- data/lib/dynamoid/dumping.rb +9 -0
- data/lib/dynamoid/dynamodb_time_zone.rb +1 -0
- data/lib/dynamoid/fields.rb +189 -16
- data/lib/dynamoid/finders.rb +65 -28
- data/lib/dynamoid/identity_map.rb +6 -0
- data/lib/dynamoid/indexes.rb +74 -15
- data/lib/dynamoid/log/formatter.rb +26 -0
- data/lib/dynamoid/middleware/identity_map.rb +1 -0
- data/lib/dynamoid/persistence.rb +452 -106
- data/lib/dynamoid/persistence/import.rb +1 -0
- data/lib/dynamoid/persistence/save.rb +1 -0
- data/lib/dynamoid/persistence/update_fields.rb +1 -0
- data/lib/dynamoid/persistence/upsert.rb +1 -0
- data/lib/dynamoid/primary_key_type_mapping.rb +1 -0
- data/lib/dynamoid/railtie.rb +1 -0
- data/lib/dynamoid/tasks/database.rb +1 -0
- data/lib/dynamoid/type_casting.rb +12 -0
- data/lib/dynamoid/undumping.rb +8 -0
- data/lib/dynamoid/validations.rb +2 -0
- data/lib/dynamoid/version.rb +1 -1
- metadata +7 -19
@@ -13,6 +13,7 @@ module Dynamoid
|
|
13
13
|
@identity_map ||= {}
|
14
14
|
end
|
15
15
|
|
16
|
+
# @private
|
16
17
|
def from_database(attrs = {})
|
17
18
|
return super if identity_map_off?
|
18
19
|
|
@@ -29,6 +30,7 @@ module Dynamoid
|
|
29
30
|
document
|
30
31
|
end
|
31
32
|
|
33
|
+
# @private
|
32
34
|
def find_by_id(id, options = {})
|
33
35
|
return super if identity_map_off?
|
34
36
|
|
@@ -41,6 +43,7 @@ module Dynamoid
|
|
41
43
|
identity_map[key] || super
|
42
44
|
end
|
43
45
|
|
46
|
+
# @private
|
44
47
|
def identity_map_key(attrs)
|
45
48
|
key = attrs[hash_key].to_s
|
46
49
|
key += "::#{attrs[range_key]}" if range_key
|
@@ -60,6 +63,7 @@ module Dynamoid
|
|
60
63
|
self.class.identity_map
|
61
64
|
end
|
62
65
|
|
66
|
+
# @private
|
63
67
|
def save(*args)
|
64
68
|
return super if self.class.identity_map_off?
|
65
69
|
|
@@ -69,6 +73,7 @@ module Dynamoid
|
|
69
73
|
result
|
70
74
|
end
|
71
75
|
|
76
|
+
# @private
|
72
77
|
def delete
|
73
78
|
return super if self.class.identity_map_off?
|
74
79
|
|
@@ -76,6 +81,7 @@ module Dynamoid
|
|
76
81
|
super
|
77
82
|
end
|
78
83
|
|
84
|
+
# @private
|
79
85
|
def identity_map_key
|
80
86
|
key = hash_key.to_s
|
81
87
|
key += "::#{range_value}" if self.class.range_key
|
data/lib/dynamoid/indexes.rb
CHANGED
@@ -15,19 +15,43 @@ module Dynamoid
|
|
15
15
|
# Defines a Global Secondary index on a table. Keys can be specified as
|
16
16
|
# hash-only, or hash & range.
|
17
17
|
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
18
|
+
# class Post
|
19
|
+
# include Dynamoid::Document
|
20
|
+
#
|
21
|
+
# field :category
|
22
|
+
#
|
23
|
+
# global_secondary_indexes hash_key: :category
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# The full example with all the options being specified:
|
27
|
+
#
|
28
|
+
# global_secondary_indexes hash_key: :category,
|
29
|
+
# range_key: :created_at,
|
30
|
+
# name: 'posts_category_created_at_index',
|
31
|
+
# projected_attributes: :all,
|
32
|
+
# read_capacity: 100,
|
33
|
+
# write_capacity: 20
|
34
|
+
#
|
35
|
+
# Global secondary index should be declared after fields for mentioned
|
36
|
+
# hash key and optional range key are declared (with method +field+)
|
37
|
+
#
|
38
|
+
# The only mandatory option is +hash_key+. Raises
|
39
|
+
# +Dynamoid::Errors::InvalidIndex+ exception if passed incorrect
|
40
|
+
# options.
|
41
|
+
#
|
42
|
+
# @param [Hash] options the options to pass for this table
|
43
|
+
# @option options [Symbol] name the name for the index; this still gets
|
44
|
+
# namespaced. If not specified, will use a default name.
|
45
|
+
# @option options [Symbol] hash_key the index hash key column.
|
46
|
+
# @option options [Symbol] range_key the index range key column (if
|
23
47
|
# applicable).
|
24
|
-
# @option options [Symbol, Array<Symbol>]
|
25
|
-
# attributes to project for this index. Can be
|
48
|
+
# @option options [Symbol, Array<Symbol>] projected_attributes table
|
49
|
+
# attributes to project for this index. Can be +:keys_only+, +:all+
|
26
50
|
# or an array of included fields. If not specified, defaults to
|
27
|
-
#
|
28
|
-
# @option options [Integer]
|
51
|
+
# +:keys_only+.
|
52
|
+
# @option options [Integer] read_capacity set the read capacity for the
|
29
53
|
# index; does not work on existing indexes.
|
30
|
-
# @option options [Integer]
|
54
|
+
# @option options [Integer] write_capacity set the write capacity for
|
31
55
|
# the index; does not work on existing indexes.
|
32
56
|
def global_secondary_index(options = {})
|
33
57
|
unless options.present?
|
@@ -55,14 +79,38 @@ module Dynamoid
|
|
55
79
|
# Defines a local secondary index on a table. Will use the same primary
|
56
80
|
# hash key as the table.
|
57
81
|
#
|
82
|
+
# class Comment
|
83
|
+
# include Dynamoid::Document
|
84
|
+
#
|
85
|
+
# table hash_key: :post_id
|
86
|
+
# range :created_at, :datetime
|
87
|
+
# field :author_id
|
88
|
+
#
|
89
|
+
# local_secondary_indexes hash_key: :author_id
|
90
|
+
# end
|
91
|
+
#
|
92
|
+
# The full example with all the options being specified:
|
93
|
+
#
|
94
|
+
# local_secondary_indexes range_key: :created_at,
|
95
|
+
# name: 'posts_created_at_index',
|
96
|
+
# projected_attributes: :all
|
97
|
+
#
|
98
|
+
# Local secondary index should be declared after fields for mentioned
|
99
|
+
# hash key and optional range key are declared (with method +field+) as
|
100
|
+
# well as after +table+ method call.
|
101
|
+
#
|
102
|
+
# The only mandatory option is +range_key+. Raises
|
103
|
+
# +Dynamoid::Errors::InvalidIndex+ exception if passed incorrect
|
104
|
+
# options.
|
105
|
+
#
|
58
106
|
# @param [Hash] options options to pass for this index.
|
59
|
-
# @option options [Symbol]
|
107
|
+
# @option options [Symbol] name the name for the index; this still gets
|
60
108
|
# namespaced. If not specified, a name is automatically generated.
|
61
|
-
# @option options [Symbol]
|
62
|
-
# @option options [Symbol, Array<Symbol>]
|
63
|
-
# attributes to project for this index. Can be
|
109
|
+
# @option options [Symbol] range_key the range key column for the index.
|
110
|
+
# @option options [Symbol, Array<Symbol>] projected_attributes table
|
111
|
+
# attributes to project for this index. Can be +:keys_only+, +:all+
|
64
112
|
# or an array of included fields. If not specified, defaults to
|
65
|
-
#
|
113
|
+
# +:keys_only+.
|
66
114
|
def local_secondary_index(options = {})
|
67
115
|
unless options.present?
|
68
116
|
raise Dynamoid::Errors::InvalidIndex, 'empty index definition'
|
@@ -94,6 +142,13 @@ module Dynamoid
|
|
94
142
|
self
|
95
143
|
end
|
96
144
|
|
145
|
+
# Returns an index by its hash key and optional range key.
|
146
|
+
#
|
147
|
+
# It works only for indexes without explicit name declared.
|
148
|
+
#
|
149
|
+
# @param hash [scalar] the hash key used to declare an index
|
150
|
+
# @param range [scalar] the range key used to declare an index (optional)
|
151
|
+
# @return [Dynamoid::Indexes::Index, nil] index object or nil if it isn't found
|
97
152
|
def find_index(hash, range = nil)
|
98
153
|
index = indexes[index_key(hash, range)]
|
99
154
|
index
|
@@ -150,6 +205,10 @@ module Dynamoid
|
|
150
205
|
local_secondary_indexes.merge(global_secondary_indexes)
|
151
206
|
end
|
152
207
|
|
208
|
+
# Returns an array of hash keys for all the declared Glocal Secondary
|
209
|
+
# Indexes.
|
210
|
+
#
|
211
|
+
# @return [Array[String]] array of hash keys
|
153
212
|
def indexed_hash_keys
|
154
213
|
global_secondary_indexes.map do |_name, index|
|
155
214
|
index.hash_key.to_s
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Dynamoid
|
2
|
+
module Log
|
3
|
+
module Formatter
|
4
|
+
|
5
|
+
# https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/Log/Formatter.html
|
6
|
+
# https://docs.aws.amazon.com/sdk-for-ruby/v2/api/Seahorse/Client/Response.html
|
7
|
+
# https://aws.amazon.com/ru/blogs/developer/logging-requests/
|
8
|
+
class Debug
|
9
|
+
def format(response)
|
10
|
+
bold = "\x1b[1m"
|
11
|
+
color = "\x1b[34m"
|
12
|
+
reset = "\x1b[0m"
|
13
|
+
|
14
|
+
[
|
15
|
+
response.context.operation.name,
|
16
|
+
"#{bold}#{color}\nRequest:\n#{reset}#{bold}",
|
17
|
+
JSON.pretty_generate(JSON.parse(response.context.http_request.body.string)),
|
18
|
+
"#{bold}#{color}\nResponse:\n#{reset}#{bold}",
|
19
|
+
JSON.pretty_generate(JSON.parse(response.context.http_response.body.string)),
|
20
|
+
reset
|
21
|
+
].join("\n")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/dynamoid/persistence.rb
CHANGED
@@ -19,6 +19,7 @@ module Dynamoid
|
|
19
19
|
attr_accessor :new_record
|
20
20
|
alias new_record? new_record
|
21
21
|
|
22
|
+
# @private
|
22
23
|
UNIX_EPOCH_DATE = Date.new(1970, 1, 1).freeze
|
23
24
|
|
24
25
|
module ClassMethods
|
@@ -30,13 +31,64 @@ module Dynamoid
|
|
30
31
|
|
31
32
|
# Create a table.
|
32
33
|
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
34
|
+
# Uses a configuration specified in a model class (with the +table+
|
35
|
+
# method) e.g. table name, schema (hash and range keys), global and local
|
36
|
+
# secondary indexes, billing mode and write/read capacity.
|
37
|
+
#
|
38
|
+
# For instance here
|
39
|
+
#
|
40
|
+
# class User
|
41
|
+
# include Dynamoid::Document
|
42
|
+
#
|
43
|
+
# table key: :uuid
|
44
|
+
# range :last_name
|
45
|
+
#
|
46
|
+
# field :first_name
|
47
|
+
# field :last_name
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# User.create_table
|
51
|
+
#
|
52
|
+
# +create_table+ method call will create a table +dynamoid_users+ with
|
53
|
+
# hash key +uuid+ and range key +name+, DynamoDB default billing mode and
|
54
|
+
# Dynamoid default read/write capacity units (100/20).
|
55
|
+
#
|
56
|
+
# All the configuration can be overridden with +options+ argument.
|
57
|
+
#
|
58
|
+
# User.create_table(table_name: 'users', read_capacity: 200, write_capacity: 40)
|
59
|
+
#
|
60
|
+
# Dynamoid creates a table synchronously by default. DynamoDB table
|
61
|
+
# creation is an asynchronous operation and a client should wait until a
|
62
|
+
# table status changes to +ACTIVE+ and a table becomes available. That's
|
63
|
+
# why Dynamoid is polling a table status and returns results only when a
|
64
|
+
# table becomes available.
|
65
|
+
#
|
66
|
+
# Polling is configured with +Dynamoid::Config.sync_retry_max_times+ and
|
67
|
+
# +Dynamoid::Config.sync_retry_wait_seconds+ configuration options. If
|
68
|
+
# table creation takes more time than configured waiting time then
|
69
|
+
# Dynamoid stops polling and returns +true+.
|
70
|
+
#
|
71
|
+
# In order to return back asynchronous behaviour and not to wait until a
|
72
|
+
# table is created the +sync: false+ option should be specified.
|
73
|
+
#
|
74
|
+
# User.create_table(sync: false)
|
75
|
+
#
|
76
|
+
# Subsequent method calls for the same table will be ignored.
|
77
|
+
#
|
78
|
+
# @param options [Hash]
|
79
|
+
#
|
80
|
+
# @option options [Symbol] :table_name name of the table
|
81
|
+
# @option options [Symbol] :id hash key name of the table
|
82
|
+
# @option options [Symbol] :hash_key_type Dynamoid type of the hash key - +:string+, +:integer+ or any other scalar type
|
83
|
+
# @option options [Hash] :range_key a Hash with range key name and type in format +{ <name> => <type> }+ e.g. +{ last_name: :string }+
|
84
|
+
# @option options [String] :billing_mode billing mode of a table - either +PROVISIONED+ (default) or +PAY_PER_REQUEST+ (for On-Demand Mode)
|
85
|
+
# @option options [Integer] :read_capacity read capacity units for the table; does not work on existing tables and is ignored when billing mode is +PAY_PER_REQUEST+
|
86
|
+
# @option options [Integer] :write_capacity write capacity units for the table; does not work on existing tables and is ignored when billing mode is +PAY_PER_REQUEST+
|
87
|
+
# @option options [Hash] :local_secondary_indexes
|
88
|
+
# @option options [Hash] :global_secondary_indexes
|
89
|
+
# @option options [true|false] :sync specifies should the method call be synchronous and wait until a table is completely created
|
90
|
+
#
|
91
|
+
# @return [true|false] Whether a table created successfully
|
40
92
|
# @since 0.4.0
|
41
93
|
def create_table(options = {})
|
42
94
|
range_key_hash = if range_key
|
@@ -63,11 +115,17 @@ module Dynamoid
|
|
63
115
|
end
|
64
116
|
end
|
65
117
|
|
66
|
-
# Deletes the table for the model
|
118
|
+
# Deletes the table for the model.
|
119
|
+
#
|
120
|
+
# Dynamoid deletes a table asynchronously and doesn't wait until a table
|
121
|
+
# is deleted completely.
|
122
|
+
#
|
123
|
+
# Subsequent method calls for the same table will be ignored.
|
67
124
|
def delete_table
|
68
125
|
Dynamoid.adapter.delete_table(table_name)
|
69
126
|
end
|
70
127
|
|
128
|
+
# @private
|
71
129
|
def from_database(attrs = {})
|
72
130
|
klass = choose_right_class(attrs)
|
73
131
|
attrs_undumped = Undumping.undump_attributes(attrs, klass.attributes)
|
@@ -76,70 +134,94 @@ module Dynamoid
|
|
76
134
|
|
77
135
|
# Create several models at once.
|
78
136
|
#
|
79
|
-
#
|
80
|
-
#
|
81
|
-
#
|
82
|
-
#
|
137
|
+
# users = User.import([{ name: 'a' }, { name: 'b' }])
|
138
|
+
#
|
139
|
+
# +import+ is a relatively low-level method and bypasses some
|
140
|
+
# mechanisms like callbacks and validation.
|
83
141
|
#
|
84
|
-
#
|
142
|
+
# It sets timestamp fields +created_at+ and +updated_at+ if they are
|
143
|
+
# blank. It sets a hash key field as well if it's blank. It expects that
|
144
|
+
# the hash key field is +string+ and sets a random UUID value if the field
|
145
|
+
# value is blank. All the field values are type casted to the declared
|
146
|
+
# types.
|
85
147
|
#
|
86
|
-
#
|
87
|
-
#
|
148
|
+
# It works efficiently and uses the `BatchWriteItem` operation. In order
|
149
|
+
# to cope with throttling it uses a backoff strategy if it's specified with
|
150
|
+
# `Dynamoid::Config.backoff` configuration option.
|
151
|
+
#
|
152
|
+
# Because of the nature of DynamoDB and its limits only 25 models can be
|
153
|
+
# saved at once. So multiple HTTP requests can be sent to DynamoDB.
|
154
|
+
#
|
155
|
+
# @param array_of_attributes [Array<Hash>]
|
156
|
+
# @return [Array] Created models
|
88
157
|
def import(array_of_attributes)
|
89
158
|
Import.call(self, array_of_attributes)
|
90
159
|
end
|
91
160
|
|
92
161
|
# Create a model.
|
93
162
|
#
|
94
|
-
# Initializes a new
|
95
|
-
#
|
163
|
+
# Initializes a new model and immediately saves it to DynamoDB.
|
164
|
+
#
|
165
|
+
# User.create(first_name: 'Mark', last_name: 'Tyler')
|
166
|
+
#
|
96
167
|
# Accepts both Hash and Array of Hashes and can create several models.
|
97
168
|
#
|
98
|
-
#
|
169
|
+
# User.create([{ first_name: 'Alice' }, { first_name: 'Bob' }])
|
170
|
+
#
|
171
|
+
# Creates a model and pass it into a block to set other attributes.
|
99
172
|
#
|
100
|
-
#
|
173
|
+
# User.create(first_name: 'Mark') do |u|
|
174
|
+
# u.age = 21
|
175
|
+
# end
|
101
176
|
#
|
177
|
+
# Validates model and runs callbacks.
|
178
|
+
#
|
179
|
+
# @param attrs [Hash|Array[Hash]] Attributes of the models
|
180
|
+
# @param block [Proc] Block to process a document after initialization
|
181
|
+
# @return [Dynamoid::Document] The created document
|
102
182
|
# @since 0.2.0
|
103
|
-
def create(attrs = {})
|
183
|
+
def create(attrs = {}, &block)
|
104
184
|
if attrs.is_a?(Array)
|
105
|
-
attrs.map { |attr| create(attr) }
|
185
|
+
attrs.map { |attr| create(attr, &block) }
|
106
186
|
else
|
107
|
-
build(attrs).tap(&:save)
|
187
|
+
build(attrs, &block).tap(&:save)
|
108
188
|
end
|
109
189
|
end
|
110
190
|
|
111
|
-
# Create
|
112
|
-
#
|
113
|
-
# Initializes a new object and immediately saves it to the database.
|
114
|
-
# Raises an exception if validation failed.
|
115
|
-
# Accepts both Hash and Array of Hashes and can create several models.
|
116
|
-
#
|
117
|
-
# @param [Hash|Array[Hash]] attrs Attributes with which to create the object.
|
191
|
+
# Create a model.
|
118
192
|
#
|
119
|
-
#
|
193
|
+
# Initializes a new object and immediately saves it to the Dynamoid.
|
194
|
+
# Raises an exception +Dynamoid::Errors::DocumentNotValid+ if validation
|
195
|
+
# failed. Accepts both Hash and Array of Hashes and can create several
|
196
|
+
# models.
|
120
197
|
#
|
198
|
+
# @param attrs [Hash|Array[Hash]] Attributes with which to create the object.
|
199
|
+
# @param block [Proc] Block to process a document after initialization
|
200
|
+
# @return [Dynamoid::Document] The created document
|
121
201
|
# @since 0.2.0
|
122
|
-
def create!(attrs = {})
|
202
|
+
def create!(attrs = {}, &block)
|
123
203
|
if attrs.is_a?(Array)
|
124
|
-
attrs.map { |attr| create!(attr) }
|
204
|
+
attrs.map { |attr| create!(attr, &block) }
|
125
205
|
else
|
126
|
-
build(attrs).tap(&:save!)
|
206
|
+
build(attrs, &block).tap(&:save!)
|
127
207
|
end
|
128
208
|
end
|
129
209
|
|
130
210
|
# Update document with provided attributes.
|
131
211
|
#
|
132
|
-
# Instantiates document and saves changes.
|
133
|
-
#
|
212
|
+
# Instantiates document and saves changes. Runs validations and
|
213
|
+
# callbacks. Don't save changes if validation fails.
|
134
214
|
#
|
135
|
-
#
|
136
|
-
# @param [Scalar value] sort key, optional
|
137
|
-
# @param [Hash] attributes
|
215
|
+
# User.update('1', age: 26)
|
138
216
|
#
|
139
|
-
#
|
217
|
+
# If range key is declared for a model it should be passed as well:
|
140
218
|
#
|
141
|
-
#
|
142
|
-
#
|
219
|
+
# User.update('1', 'Tylor', age: 26)
|
220
|
+
#
|
221
|
+
# @param hash_key [Scalar value] hash key
|
222
|
+
# @param range_key_value [Scalar value] range key (optional)
|
223
|
+
# @param attrs [Hash]
|
224
|
+
# @return [Dynamoid::Document] Updated document
|
143
225
|
def update(hash_key, range_key_value = nil, attrs)
|
144
226
|
model = find(hash_key, range_key: range_key_value, consistent_read: true)
|
145
227
|
model.update_attributes(attrs)
|
@@ -148,17 +230,21 @@ module Dynamoid
|
|
148
230
|
|
149
231
|
# Update document with provided attributes.
|
150
232
|
#
|
151
|
-
# Instantiates document and saves changes.
|
152
|
-
#
|
233
|
+
# Instantiates document and saves changes. Runs validations and
|
234
|
+
# callbacks.
|
235
|
+
#
|
236
|
+
# User.update!('1', age: 26)
|
153
237
|
#
|
154
|
-
#
|
155
|
-
# @param [Scalar value] sort key, optional
|
156
|
-
# @param [Hash] attributes
|
238
|
+
# If range key is declared for a model it should be passed as well:
|
157
239
|
#
|
158
|
-
#
|
240
|
+
# User.update('1', 'Tylor', age: 26)
|
159
241
|
#
|
160
|
-
#
|
161
|
-
#
|
242
|
+
# Raises +Dynamoid::Errors::DocumentNotValid+ exception if validation fails.
|
243
|
+
#
|
244
|
+
# @param hash_key [Scalar value] hash key
|
245
|
+
# @param range_key_value [Scalar value] range key (optional)
|
246
|
+
# @param attrs [Hash]
|
247
|
+
# @return [Dynamoid::Document] Updated document
|
162
248
|
def update!(hash_key, range_key_value = nil, attrs)
|
163
249
|
model = find(hash_key, range_key: range_key_value, consistent_read: true)
|
164
250
|
model.update_attributes!(attrs)
|
@@ -167,23 +253,34 @@ module Dynamoid
|
|
167
253
|
|
168
254
|
# Update document.
|
169
255
|
#
|
170
|
-
#
|
171
|
-
#
|
172
|
-
#
|
173
|
-
#
|
256
|
+
# Doesn't run validations and callbacks.
|
257
|
+
#
|
258
|
+
# User.update_fields('1', age: 26)
|
259
|
+
#
|
260
|
+
# If range key is declared for a model it should be passed as well:
|
261
|
+
#
|
262
|
+
# User.update_fields('1', 'Tylor', age: 26)
|
263
|
+
#
|
264
|
+
# Can make a conditional update so a document will be updated only if it
|
265
|
+
# meets the specified conditions. Conditions can be specified as a +Hash+
|
266
|
+
# with +:if+ key:
|
267
|
+
#
|
268
|
+
# User.update_fields('1', { age: 26 }, if: { version: 1 })
|
174
269
|
#
|
175
|
-
#
|
176
|
-
#
|
177
|
-
# @param [Hash] attributes
|
178
|
-
# @param [Hash] conditions
|
270
|
+
# Here +User+ model has an integer +version+ field and the document will
|
271
|
+
# be updated only if the +version+ attribute currently has value 1.
|
179
272
|
#
|
180
|
-
#
|
273
|
+
# If a document with specified hash and range keys doesn't exist or
|
274
|
+
# conditions were specified and failed the method call returns +nil+.
|
181
275
|
#
|
182
|
-
#
|
183
|
-
#
|
276
|
+
# +update_fields+ uses the +UpdateItem+ operation so it saves changes and
|
277
|
+
# loads an updated document back with one HTTP request.
|
184
278
|
#
|
185
|
-
# @
|
186
|
-
#
|
279
|
+
# @param hash_key_value [Scalar value] hash key
|
280
|
+
# @param range_key_value [Scalar value] range key (optional)
|
281
|
+
# @param attrs [Hash]
|
282
|
+
# @param conditions [Hash] (optional)
|
283
|
+
# @return [Dynamoid::Document|nil] Updated document
|
187
284
|
def update_fields(hash_key_value, range_key_value = nil, attrs = {}, conditions = {})
|
188
285
|
optional_params = [range_key_value, attrs, conditions].compact
|
189
286
|
if optional_params.first.is_a?(Hash)
|
@@ -201,25 +298,37 @@ module Dynamoid
|
|
201
298
|
conditions: conditions)
|
202
299
|
end
|
203
300
|
|
204
|
-
# Update existing document or create new one.
|
301
|
+
# Update an existing document or create a new one.
|
205
302
|
#
|
206
|
-
#
|
207
|
-
#
|
303
|
+
# If a document with specified hash and range keys doesn't exist it
|
304
|
+
# creates a new document with specified attributes. Doesn't run
|
305
|
+
# validations and callbacks.
|
208
306
|
#
|
209
|
-
#
|
210
|
-
# Changes attibutes and loads new document version with one API call.
|
211
|
-
# Doesn't run validations and callbacks. Can make conditional update.
|
212
|
-
# If specified conditions failed - returns `nil`.
|
307
|
+
# User.upsert('1', age: 26)
|
213
308
|
#
|
214
|
-
#
|
215
|
-
# @param [Scalar value] sort key (optional)
|
216
|
-
# @param [Hash] attributes
|
217
|
-
# @param [Hash] conditions
|
309
|
+
# If range key is declared for a model it should be passed as well:
|
218
310
|
#
|
219
|
-
#
|
311
|
+
# User.upsert('1', 'Tylor', age: 26)
|
220
312
|
#
|
221
|
-
#
|
222
|
-
#
|
313
|
+
# Can make a conditional update so a document will be updated only if it
|
314
|
+
# meets the specified conditions. Conditions can be specified as a +Hash+
|
315
|
+
# with +:if+ key:
|
316
|
+
#
|
317
|
+
# User.upsert('1', { age: 26 }, if: { version: 1 })
|
318
|
+
#
|
319
|
+
# Here +User+ model has an integer +version+ field and the document will
|
320
|
+
# be updated only if the +version+ attribute currently has value 1.
|
321
|
+
#
|
322
|
+
# If conditions were specified and failed the method call returns +nil+.
|
323
|
+
#
|
324
|
+
# +upsert+ uses the +UpdateItem+ operation so it saves changes and loads
|
325
|
+
# an updated document back with one HTTP request.
|
326
|
+
#
|
327
|
+
# @param hash_key_value [Scalar value] hash key
|
328
|
+
# @param range_key_value [Scalar value] range key (optional)
|
329
|
+
# @param attrs [Hash]
|
330
|
+
# @param conditions [Hash] (optional)
|
331
|
+
# @return [Dynamoid::Document|nil] Updated document
|
223
332
|
def upsert(hash_key_value, range_key_value = nil, attrs = {}, conditions = {})
|
224
333
|
optional_params = [range_key_value, attrs, conditions].compact
|
225
334
|
if optional_params.first.is_a?(Hash)
|
@@ -237,19 +346,27 @@ module Dynamoid
|
|
237
346
|
conditions: conditions)
|
238
347
|
end
|
239
348
|
|
240
|
-
# Increase numeric field by specified value.
|
349
|
+
# Increase a numeric field by specified value.
|
350
|
+
#
|
351
|
+
# User.inc('1', age: 2)
|
241
352
|
#
|
242
353
|
# Can update several fields at once.
|
243
|
-
# Uses efficient low-level `UpdateItem` API call.
|
244
354
|
#
|
245
|
-
#
|
246
|
-
#
|
247
|
-
#
|
355
|
+
# User.inc('1', age: 2, version: 1)
|
356
|
+
#
|
357
|
+
# If range key is declared for a model it should be passed as well:
|
248
358
|
#
|
249
|
-
#
|
359
|
+
# User.inc('1', 'Tylor', age: 2)
|
250
360
|
#
|
251
|
-
#
|
252
|
-
#
|
361
|
+
# Uses efficient low-level +UpdateItem+ operation and does only one HTTP
|
362
|
+
# request.
|
363
|
+
#
|
364
|
+
# Doesn't run validations and callbacks. Doesn't update +created_at+ and
|
365
|
+
# +updated_at+ as well.
|
366
|
+
#
|
367
|
+
# @param hash_key_value [Scalar value] hash key
|
368
|
+
# @param range_key_value [Scalar value] range key (optional)
|
369
|
+
# @param counters [Hash] value to increase by
|
253
370
|
def inc(hash_key_value, range_key_value = nil, counters)
|
254
371
|
options = if range_key
|
255
372
|
value_casted = TypeCasting.cast_field(range_key_value, attributes[range_key])
|
@@ -270,8 +387,17 @@ module Dynamoid
|
|
270
387
|
end
|
271
388
|
end
|
272
389
|
|
273
|
-
#
|
390
|
+
# Update document timestamps.
|
391
|
+
#
|
392
|
+
# Set +updated_at+ attribute to current DateTime.
|
393
|
+
#
|
394
|
+
# post.touch
|
274
395
|
#
|
396
|
+
# Can update another field in addition with the same timestamp if it's name passed as argument.
|
397
|
+
#
|
398
|
+
# user.touch(:last_login_at)
|
399
|
+
#
|
400
|
+
# @param name [Symbol] attribute name to update (optional)
|
275
401
|
def touch(name = nil)
|
276
402
|
now = DateTime.now
|
277
403
|
self.updated_at = now
|
@@ -279,15 +405,67 @@ module Dynamoid
|
|
279
405
|
save
|
280
406
|
end
|
281
407
|
|
282
|
-
# Is this object persisted in
|
408
|
+
# Is this object persisted in DynamoDB?
|
409
|
+
#
|
410
|
+
# user = User.new
|
411
|
+
# user.persisted? # => false
|
283
412
|
#
|
413
|
+
# user.save
|
414
|
+
# user.persisted? # => true
|
415
|
+
#
|
416
|
+
# @return [true|false]
|
284
417
|
# @since 0.2.0
|
285
418
|
def persisted?
|
286
419
|
!(new_record? || @destroyed)
|
287
420
|
end
|
288
421
|
|
289
|
-
#
|
422
|
+
# Create new model or persist changes.
|
423
|
+
#
|
424
|
+
# Run the validation and callbacks. Returns +true+ if saving is successful
|
425
|
+
# and +false+ otherwise.
|
426
|
+
#
|
427
|
+
# user = User.new
|
428
|
+
# user.save # => true
|
429
|
+
#
|
430
|
+
# user.age = 26
|
431
|
+
# user.save # => true
|
432
|
+
#
|
433
|
+
# Validation can be skipped with +validate: false+ option:
|
434
|
+
#
|
435
|
+
# user = User.new(age: -1)
|
436
|
+
# user.save(validate: false) # => true
|
437
|
+
#
|
438
|
+
# +save+ by default sets timestamps attributes - +created_at+ and
|
439
|
+
# +updated_at+ when creates new model and updates +updated_at+ attribute
|
440
|
+
# when update already existing one.
|
290
441
|
#
|
442
|
+
# Changing +updated_at+ attribute at updating a model can be skipped with
|
443
|
+
# +touch: false+ option:
|
444
|
+
#
|
445
|
+
# user.save(touch: false)
|
446
|
+
#
|
447
|
+
# If a model is new and hash key (+id+ by default) is not assigned yet
|
448
|
+
# it was assigned implicitly with random UUID value.
|
449
|
+
#
|
450
|
+
# If +lock_version+ attribute is declared it will be incremented. If it's blank then it will be initialized with 1.
|
451
|
+
#
|
452
|
+
# +save+ method call raises +Dynamoid::Errors::RecordNotUnique+ exception
|
453
|
+
# if primary key (hash key + optional range key) already exists in a
|
454
|
+
# table.
|
455
|
+
#
|
456
|
+
# +save+ method call raises +Dynamoid::Errors::StaleObjectError+ exception
|
457
|
+
# if there is +lock_version+ attribute and the document in a table was
|
458
|
+
# already changed concurrently and +lock_version+ was consequently
|
459
|
+
# increased.
|
460
|
+
#
|
461
|
+
# When a table is not created yet the first +save+ method call will create
|
462
|
+
# a table. It's useful in test environment to avoid explicit table
|
463
|
+
# creation.
|
464
|
+
#
|
465
|
+
# @param options [Hash] (optional)
|
466
|
+
# @option options [true|false] :validate validate a model or not - +true+ by default (optional)
|
467
|
+
# @option options [true|false] :touch update tiemstamps fields or not - +true+ by default (optional)
|
468
|
+
# @return [true|false] Whether saving successful or not
|
291
469
|
# @since 0.2.0
|
292
470
|
def save(options = {})
|
293
471
|
self.class.create_table(sync: true)
|
@@ -307,20 +485,29 @@ module Dynamoid
|
|
307
485
|
end
|
308
486
|
end
|
309
487
|
|
310
|
-
#
|
488
|
+
# Update multiple attributes at once, saving the object once the updates
|
489
|
+
# are complete. Returns +true+ if saving is successful and +false+
|
490
|
+
# otherwise.
|
311
491
|
#
|
312
|
-
#
|
492
|
+
# user.update_attributes(age: 27, last_name: 'Tylor')
|
313
493
|
#
|
494
|
+
# @param attributes [Hash] a hash of attributes to update
|
495
|
+
# @return [true|false] Whether updating successful or not
|
314
496
|
# @since 0.2.0
|
315
497
|
def update_attributes(attributes)
|
316
498
|
attributes.each { |attribute, value| write_attribute(attribute, value) }
|
317
499
|
save
|
318
500
|
end
|
319
501
|
|
320
|
-
#
|
321
|
-
#
|
502
|
+
# Update multiple attributes at once, saving the object once the updates
|
503
|
+
# are complete.
|
504
|
+
#
|
505
|
+
# user.update_attributes!(age: 27, last_name: 'Tylor')
|
322
506
|
#
|
323
|
-
#
|
507
|
+
# Raises a +Dynamoid::Errors::DocumentNotValid+ exception if some vaidation
|
508
|
+
# fails.
|
509
|
+
#
|
510
|
+
# @param attributes [Hash] a hash of attributes to update
|
324
511
|
def update_attributes!(attributes)
|
325
512
|
attributes.each { |attribute, value| write_attribute(attribute, value) }
|
326
513
|
save!
|
@@ -328,20 +515,68 @@ module Dynamoid
|
|
328
515
|
|
329
516
|
# Update a single attribute, saving the object afterwards.
|
330
517
|
#
|
331
|
-
#
|
332
|
-
#
|
518
|
+
# Returns +true+ if saving is successful and +false+ otherwise.
|
519
|
+
#
|
520
|
+
# user.update_attribute(:last_name, 'Tylor')
|
333
521
|
#
|
522
|
+
# @param attribute [Symbol] attribute name to update
|
523
|
+
# @param value [Object] the value to assign it
|
524
|
+
# @return [Dynamoid::Document] self
|
334
525
|
# @since 0.2.0
|
335
526
|
def update_attribute(attribute, value)
|
336
527
|
write_attribute(attribute, value)
|
337
528
|
save
|
338
529
|
end
|
339
530
|
|
531
|
+
# Update a model.
|
532
|
+
#
|
533
|
+
# Runs validation and callbacks. Reloads all attribute values.
|
534
|
+
#
|
535
|
+
# Accepts mandatory block in order to specify operations which will modify
|
536
|
+
# attributes. Supports following operations: +add+, +delete+ and +set+.
|
537
|
+
#
|
538
|
+
# Operation +add+ just adds a value for numeric attributes and join
|
539
|
+
# collections if attribute is a collection (one of +array+, +set+ or
|
540
|
+
# +map+).
|
541
|
+
#
|
542
|
+
# user.update do |t|
|
543
|
+
# t.add(age: 1, followers_count: 5)
|
544
|
+
# t.add(hobbies: ['skying', 'climbing'])
|
545
|
+
# end
|
546
|
+
#
|
547
|
+
# Operation +delete+ is applied to collection attribute types and
|
548
|
+
# substructs one collection from another.
|
340
549
|
#
|
341
|
-
#
|
342
|
-
#
|
550
|
+
# user.update do |t|
|
551
|
+
# t.delete(hobbies: ['skying'])
|
552
|
+
# end
|
343
553
|
#
|
554
|
+
# Operation +set+ just changes an attribute value:
|
344
555
|
#
|
556
|
+
# user.update do |t|
|
557
|
+
# t.set(age: 21)
|
558
|
+
# end
|
559
|
+
#
|
560
|
+
# All the operations works like +ADD+, +DELETE+ and +PUT+ actions supported
|
561
|
+
# by +AttributeUpdates+
|
562
|
+
# {parameter}[https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LegacyConditionalParameters.AttributeUpdates.html]
|
563
|
+
# of +UpdateItem+ operation.
|
564
|
+
#
|
565
|
+
# Can update a model conditionaly:
|
566
|
+
#
|
567
|
+
# user.update(if: { age: 20 }) do |t|
|
568
|
+
# t.add(age: 1)
|
569
|
+
# end
|
570
|
+
#
|
571
|
+
# If a document doesn't meet conditions it raises
|
572
|
+
# +Dynamoid::Errors::StaleObjectError+ exception.
|
573
|
+
#
|
574
|
+
# It will increment the +lock_version+ attribute if a table has the column,
|
575
|
+
# but will not check it. Thus, a concurrent +save+ call will never cause an
|
576
|
+
# +update!+ to fail, but an +update!+ may cause a concurrent +save+ to
|
577
|
+
# fail.
|
578
|
+
#
|
579
|
+
# @param conditions [Hash] Conditions on model attributes to make a conditional update (optional)
|
345
580
|
def update!(conditions = {})
|
346
581
|
run_callbacks(:update) do
|
347
582
|
options = range_key ? { range_key: Dumping.dump_field(read_attribute(range_key), self.class.attributes[range_key]) } : {}
|
@@ -365,6 +600,54 @@ module Dynamoid
|
|
365
600
|
end
|
366
601
|
end
|
367
602
|
|
603
|
+
# Update a model.
|
604
|
+
#
|
605
|
+
# Runs validation and callbacks. Reloads all attribute values.
|
606
|
+
#
|
607
|
+
# Accepts mandatory block in order to specify operations which will modify
|
608
|
+
# attributes. Supports following operations: +add+, +delete+ and +set+.
|
609
|
+
#
|
610
|
+
# Operation +add+ just adds a value for numeric attributes and join
|
611
|
+
# collections if attribute is a collection (one of +array+, +set+ or
|
612
|
+
# +map+).
|
613
|
+
#
|
614
|
+
# user.update do |t|
|
615
|
+
# t.add(age: 1, followers_count: 5)
|
616
|
+
# t.add(hobbies: ['skying', 'climbing'])
|
617
|
+
# end
|
618
|
+
#
|
619
|
+
# Operation +delete+ is applied to collection attribute types and
|
620
|
+
# substructs one collection from another.
|
621
|
+
#
|
622
|
+
# user.update do |t|
|
623
|
+
# t.delete(hobbies: ['skying'])
|
624
|
+
# end
|
625
|
+
#
|
626
|
+
# Operation +set+ just changes an attribute value:
|
627
|
+
#
|
628
|
+
# user.update do |t|
|
629
|
+
# t.set(age: 21)
|
630
|
+
# end
|
631
|
+
#
|
632
|
+
# All the operations works like +ADD+, +DELETE+ and +PUT+ actions supported
|
633
|
+
# by +AttributeUpdates+
|
634
|
+
# {parameter}[https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LegacyConditionalParameters.AttributeUpdates.html]
|
635
|
+
# of +UpdateItem+ operation.
|
636
|
+
#
|
637
|
+
# Can update a model conditionaly:
|
638
|
+
#
|
639
|
+
# user.update(if: { age: 20 }) do |t|
|
640
|
+
# t.add(age: 1)
|
641
|
+
# end
|
642
|
+
#
|
643
|
+
# If a document doesn't meet conditions it just returns +false+. Otherwise it returns +true+.
|
644
|
+
#
|
645
|
+
# It will increment the +lock_version+ attribute if a table has the column,
|
646
|
+
# but will not check it. Thus, a concurrent +save+ call will never cause an
|
647
|
+
# +update!+ to fail, but an +update!+ may cause a concurrent +save+ to
|
648
|
+
# fail.
|
649
|
+
#
|
650
|
+
# @param conditions [Hash] Conditions on model attributes to make a conditional update (optional)
|
368
651
|
def update(conditions = {}, &block)
|
369
652
|
update!(conditions, &block)
|
370
653
|
true
|
@@ -372,38 +655,86 @@ module Dynamoid
|
|
372
655
|
false
|
373
656
|
end
|
374
657
|
|
375
|
-
#
|
376
|
-
#
|
658
|
+
# Change numeric attribute value.
|
659
|
+
#
|
660
|
+
# Initializes attribute to zero if +nil+ and adds the specified value (by
|
661
|
+
# default is 1). Only makes sense for number-based attributes.
|
662
|
+
#
|
663
|
+
# user.increment(:followers_count)
|
664
|
+
# user.increment(:followers_count, 2)
|
665
|
+
#
|
666
|
+
# @param attribute [Symbol] attribute name
|
667
|
+
# @param by [Numeric] value to add (optional)
|
668
|
+
# @return [Dynamoid::Document] self
|
377
669
|
def increment(attribute, by = 1)
|
378
670
|
self[attribute] ||= 0
|
379
671
|
self[attribute] += by
|
380
672
|
self
|
381
673
|
end
|
382
674
|
|
383
|
-
#
|
384
|
-
#
|
675
|
+
# Change numeric attribute value and save a model.
|
676
|
+
#
|
677
|
+
# Initializes attribute to zero if +nil+ and adds the specified value (by
|
678
|
+
# default is 1). Only makes sense for number-based attributes.
|
679
|
+
#
|
680
|
+
# user.increment!(:followers_count)
|
681
|
+
# user.increment!(:followers_count, 2)
|
682
|
+
#
|
683
|
+
# Returns +true+ if a model was saved and +false+ otherwise.
|
684
|
+
#
|
685
|
+
# @param attribute [Symbol] attribute name
|
686
|
+
# @param by [Numeric] value to add (optional)
|
687
|
+
# @return [true|false] whether saved model successfully
|
385
688
|
def increment!(attribute, by = 1)
|
386
689
|
increment(attribute, by)
|
387
690
|
save
|
388
691
|
end
|
389
692
|
|
390
|
-
#
|
391
|
-
#
|
693
|
+
# Change numeric attribute value.
|
694
|
+
#
|
695
|
+
# Initializes attribute to zero if +nil+ and subtracts the specified value
|
696
|
+
# (by default is 1). Only makes sense for number-based attributes.
|
697
|
+
#
|
698
|
+
# user.decrement(:followers_count)
|
699
|
+
# user.decrement(:followers_count, 2)
|
700
|
+
#
|
701
|
+
# @param attribute [Symbol] attribute name
|
702
|
+
# @param by [Numeric] value to subtract (optional)
|
703
|
+
# @return [Dynamoid::Document] self
|
392
704
|
def decrement(attribute, by = 1)
|
393
705
|
self[attribute] ||= 0
|
394
706
|
self[attribute] -= by
|
395
707
|
self
|
396
708
|
end
|
397
709
|
|
398
|
-
#
|
399
|
-
#
|
710
|
+
# Change numeric attribute value and save a model.
|
711
|
+
#
|
712
|
+
# Initializes attribute to zero if +nil+ and subtracts the specified value
|
713
|
+
# (by default is 1). Only makes sense for number-based attributes.
|
714
|
+
#
|
715
|
+
# user.decrement!(:followers_count)
|
716
|
+
# user.decrement!(:followers_count, 2)
|
717
|
+
#
|
718
|
+
# Returns +true+ if a model was saved and +false+ otherwise.
|
719
|
+
#
|
720
|
+
# @param attribute [Symbol] attribute name
|
721
|
+
# @param by [Numeric] value to subtract (optional)
|
722
|
+
# @return [true|false] whether saved model successfully
|
400
723
|
def decrement!(attribute, by = 1)
|
401
724
|
decrement(attribute, by)
|
402
725
|
save
|
403
726
|
end
|
404
727
|
|
405
|
-
# Delete
|
728
|
+
# Delete a model.
|
729
|
+
#
|
730
|
+
# Runs callbacks.
|
406
731
|
#
|
732
|
+
# Supports optimistic locking with the +lock_version+ attribute and doesn't
|
733
|
+
# delete a model if it's already changed.
|
734
|
+
#
|
735
|
+
# Returns +true+ if deleted successfully and +false+ otherwise.
|
736
|
+
#
|
737
|
+
# @return [true|false] whether deleted successfully
|
407
738
|
# @since 0.2.0
|
408
739
|
def destroy
|
409
740
|
ret = run_callbacks(:destroy) do
|
@@ -415,11 +746,26 @@ module Dynamoid
|
|
415
746
|
ret == false ? false : self
|
416
747
|
end
|
417
748
|
|
749
|
+
# Delete a model.
|
750
|
+
#
|
751
|
+
# Runs callbacks.
|
752
|
+
#
|
753
|
+
# Supports optimistic locking with the +lock_version+ attribute and doesn't
|
754
|
+
# delete a model if it's already changed.
|
755
|
+
#
|
756
|
+
# Raises +Dynamoid::Errors::RecordNotDestroyed+ exception if model deleting
|
757
|
+
# failed.
|
418
758
|
def destroy!
|
419
759
|
destroy || (raise Dynamoid::Errors::RecordNotDestroyed, self)
|
420
760
|
end
|
421
761
|
|
422
|
-
# Delete
|
762
|
+
# Delete a model.
|
763
|
+
#
|
764
|
+
# Supports optimistic locking with the +lock_version+ attribute and doesn't
|
765
|
+
# delete a model if it's already changed.
|
766
|
+
#
|
767
|
+
# Raises +Dynamoid::Errors::StaleObjectError+ exception if cannot delete a
|
768
|
+
# model.
|
423
769
|
#
|
424
770
|
# @since 0.2.0
|
425
771
|
def delete
|