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