adept_dynamoid 0.5.0.8 → 0.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.
- data/Rakefile +2 -2
- data/VERSION +1 -1
- data/adept_dynamoid.gemspec +195 -0
- data/lib/dynamoid/adapter.rb +111 -23
- data/lib/dynamoid/adapter/aws_sdk.rb +23 -3
- data/lib/dynamoid/criteria/chain.rb +65 -1
- data/lib/dynamoid/fields.rb +2 -0
- data/spec/dynamoid/adapter/aws_sdk_spec.rb +135 -1
- data/spec/dynamoid/adapter_spec.rb +54 -1
- data/spec/dynamoid/criteria/chain_spec.rb +24 -0
- metadata +6 -3
data/Rakefile
CHANGED
@@ -14,11 +14,11 @@ require 'rake'
|
|
14
14
|
require 'jeweler'
|
15
15
|
Jeweler::Tasks.new do |gem|
|
16
16
|
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
-
gem.name = "
|
17
|
+
gem.name = "dynamoid"
|
18
18
|
gem.homepage = "http://github.com/Veraticus/Dynamoid"
|
19
19
|
gem.license = "MIT"
|
20
20
|
gem.summary = "Dynamoid is an ORM for Amazon's DynamoDB"
|
21
|
-
gem.description = "Dynamoid is an ORM for Amazon's DynamoDB that supports offline development, associations, querying, and everything else you'd expect from an ActiveRecord-style replacement.
|
21
|
+
gem.description = "Dynamoid is an ORM for Amazon's DynamoDB that supports offline development, associations, querying, and everything else you'd expect from an ActiveRecord-style replacement."
|
22
22
|
gem.email = "josh@joshsymonds.com"
|
23
23
|
gem.authors = ["Josh Symonds"]
|
24
24
|
# dependencies defined in Gemfile
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.0.0
|
@@ -0,0 +1,195 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "adept_dynamoid"
|
8
|
+
s.version = "0.6.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Josh Symonds"]
|
12
|
+
s.date = "2012-12-05"
|
13
|
+
s.description = "Dynamoid is an ORM for Amazon's DynamoDB that supports offline development, associations, querying, and everything else you'd expect from an ActiveRecord-style replacement. Make sure you add require 'dynamoid' to before your configure script with adept_dynamoid"
|
14
|
+
s.email = "josh@joshsymonds.com"
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE.txt",
|
17
|
+
"README.markdown"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
".project",
|
22
|
+
".rspec",
|
23
|
+
"Dynamoid.gemspec",
|
24
|
+
"Gemfile",
|
25
|
+
"Gemfile.lock",
|
26
|
+
"LICENSE.txt",
|
27
|
+
"README.markdown",
|
28
|
+
"Rakefile",
|
29
|
+
"VERSION",
|
30
|
+
"adept_dynamoid.gemspec",
|
31
|
+
"doc/.nojekyll",
|
32
|
+
"doc/Dynamoid.html",
|
33
|
+
"doc/Dynamoid/Adapter.html",
|
34
|
+
"doc/Dynamoid/Adapter/AwsSdk.html",
|
35
|
+
"doc/Dynamoid/Adapter/Local.html",
|
36
|
+
"doc/Dynamoid/Associations.html",
|
37
|
+
"doc/Dynamoid/Associations/Association.html",
|
38
|
+
"doc/Dynamoid/Associations/BelongsTo.html",
|
39
|
+
"doc/Dynamoid/Associations/ClassMethods.html",
|
40
|
+
"doc/Dynamoid/Associations/HasAndBelongsToMany.html",
|
41
|
+
"doc/Dynamoid/Associations/HasMany.html",
|
42
|
+
"doc/Dynamoid/Associations/HasOne.html",
|
43
|
+
"doc/Dynamoid/Associations/ManyAssociation.html",
|
44
|
+
"doc/Dynamoid/Associations/SingleAssociation.html",
|
45
|
+
"doc/Dynamoid/Components.html",
|
46
|
+
"doc/Dynamoid/Config.html",
|
47
|
+
"doc/Dynamoid/Config/Options.html",
|
48
|
+
"doc/Dynamoid/Criteria.html",
|
49
|
+
"doc/Dynamoid/Criteria/Chain.html",
|
50
|
+
"doc/Dynamoid/Criteria/ClassMethods.html",
|
51
|
+
"doc/Dynamoid/Document.html",
|
52
|
+
"doc/Dynamoid/Document/ClassMethods.html",
|
53
|
+
"doc/Dynamoid/Errors.html",
|
54
|
+
"doc/Dynamoid/Errors/DocumentNotValid.html",
|
55
|
+
"doc/Dynamoid/Errors/Error.html",
|
56
|
+
"doc/Dynamoid/Errors/InvalidField.html",
|
57
|
+
"doc/Dynamoid/Errors/MissingRangeKey.html",
|
58
|
+
"doc/Dynamoid/Fields.html",
|
59
|
+
"doc/Dynamoid/Fields/ClassMethods.html",
|
60
|
+
"doc/Dynamoid/Finders.html",
|
61
|
+
"doc/Dynamoid/Finders/ClassMethods.html",
|
62
|
+
"doc/Dynamoid/Indexes.html",
|
63
|
+
"doc/Dynamoid/Indexes/ClassMethods.html",
|
64
|
+
"doc/Dynamoid/Indexes/Index.html",
|
65
|
+
"doc/Dynamoid/Persistence.html",
|
66
|
+
"doc/Dynamoid/Persistence/ClassMethods.html",
|
67
|
+
"doc/Dynamoid/Validations.html",
|
68
|
+
"doc/_index.html",
|
69
|
+
"doc/class_list.html",
|
70
|
+
"doc/css/common.css",
|
71
|
+
"doc/css/full_list.css",
|
72
|
+
"doc/css/style.css",
|
73
|
+
"doc/file.LICENSE.html",
|
74
|
+
"doc/file.README.html",
|
75
|
+
"doc/file_list.html",
|
76
|
+
"doc/frames.html",
|
77
|
+
"doc/index.html",
|
78
|
+
"doc/js/app.js",
|
79
|
+
"doc/js/full_list.js",
|
80
|
+
"doc/js/jquery.js",
|
81
|
+
"doc/method_list.html",
|
82
|
+
"doc/top-level-namespace.html",
|
83
|
+
"lib/dynamoid.rb",
|
84
|
+
"lib/dynamoid/adapter.rb",
|
85
|
+
"lib/dynamoid/adapter/aws_sdk.rb",
|
86
|
+
"lib/dynamoid/associations.rb",
|
87
|
+
"lib/dynamoid/associations/association.rb",
|
88
|
+
"lib/dynamoid/associations/belongs_to.rb",
|
89
|
+
"lib/dynamoid/associations/has_and_belongs_to_many.rb",
|
90
|
+
"lib/dynamoid/associations/has_many.rb",
|
91
|
+
"lib/dynamoid/associations/has_one.rb",
|
92
|
+
"lib/dynamoid/associations/many_association.rb",
|
93
|
+
"lib/dynamoid/associations/single_association.rb",
|
94
|
+
"lib/dynamoid/components.rb",
|
95
|
+
"lib/dynamoid/config.rb",
|
96
|
+
"lib/dynamoid/config/options.rb",
|
97
|
+
"lib/dynamoid/criteria.rb",
|
98
|
+
"lib/dynamoid/criteria/chain.rb",
|
99
|
+
"lib/dynamoid/dirty.rb",
|
100
|
+
"lib/dynamoid/document.rb",
|
101
|
+
"lib/dynamoid/errors.rb",
|
102
|
+
"lib/dynamoid/fields.rb",
|
103
|
+
"lib/dynamoid/finders.rb",
|
104
|
+
"lib/dynamoid/identity_map.rb",
|
105
|
+
"lib/dynamoid/indexes.rb",
|
106
|
+
"lib/dynamoid/indexes/index.rb",
|
107
|
+
"lib/dynamoid/middleware/identity_map.rb",
|
108
|
+
"lib/dynamoid/persistence.rb",
|
109
|
+
"lib/dynamoid/validations.rb",
|
110
|
+
"spec/app/models/address.rb",
|
111
|
+
"spec/app/models/camel_case.rb",
|
112
|
+
"spec/app/models/magazine.rb",
|
113
|
+
"spec/app/models/message.rb",
|
114
|
+
"spec/app/models/sponsor.rb",
|
115
|
+
"spec/app/models/subscription.rb",
|
116
|
+
"spec/app/models/tweet.rb",
|
117
|
+
"spec/app/models/user.rb",
|
118
|
+
"spec/dynamoid/adapter/aws_sdk_spec.rb",
|
119
|
+
"spec/dynamoid/adapter_spec.rb",
|
120
|
+
"spec/dynamoid/associations/association_spec.rb",
|
121
|
+
"spec/dynamoid/associations/belongs_to_spec.rb",
|
122
|
+
"spec/dynamoid/associations/has_and_belongs_to_many_spec.rb",
|
123
|
+
"spec/dynamoid/associations/has_many_spec.rb",
|
124
|
+
"spec/dynamoid/associations/has_one_spec.rb",
|
125
|
+
"spec/dynamoid/associations_spec.rb",
|
126
|
+
"spec/dynamoid/config_spec.rb",
|
127
|
+
"spec/dynamoid/criteria/chain_spec.rb",
|
128
|
+
"spec/dynamoid/criteria_spec.rb",
|
129
|
+
"spec/dynamoid/dirty_spec.rb",
|
130
|
+
"spec/dynamoid/document_spec.rb",
|
131
|
+
"spec/dynamoid/fields_spec.rb",
|
132
|
+
"spec/dynamoid/finders_spec.rb",
|
133
|
+
"spec/dynamoid/identity_map_spec.rb",
|
134
|
+
"spec/dynamoid/indexes/index_spec.rb",
|
135
|
+
"spec/dynamoid/indexes_spec.rb",
|
136
|
+
"spec/dynamoid/persistence_spec.rb",
|
137
|
+
"spec/dynamoid/validations_spec.rb",
|
138
|
+
"spec/dynamoid_spec.rb",
|
139
|
+
"spec/spec_helper.rb"
|
140
|
+
]
|
141
|
+
s.homepage = "http://github.com/Veraticus/Dynamoid"
|
142
|
+
s.licenses = ["MIT"]
|
143
|
+
s.require_paths = ["lib"]
|
144
|
+
s.rubygems_version = "1.8.24"
|
145
|
+
s.summary = "Dynamoid is an ORM for Amazon's DynamoDB"
|
146
|
+
|
147
|
+
if s.respond_to? :specification_version then
|
148
|
+
s.specification_version = 3
|
149
|
+
|
150
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
151
|
+
s.add_runtime_dependency(%q<activemodel>, [">= 0"])
|
152
|
+
s.add_runtime_dependency(%q<tzinfo>, [">= 0"])
|
153
|
+
s.add_runtime_dependency(%q<aws-sdk>, [">= 0"])
|
154
|
+
s.add_development_dependency(%q<rake>, [">= 0"])
|
155
|
+
s.add_development_dependency(%q<rspec>, [">= 0"])
|
156
|
+
s.add_development_dependency(%q<bundler>, [">= 0"])
|
157
|
+
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
158
|
+
s.add_development_dependency(%q<yard>, [">= 0"])
|
159
|
+
s.add_development_dependency(%q<redcarpet>, ["= 1.17.2"])
|
160
|
+
s.add_development_dependency(%q<github-markup>, [">= 0"])
|
161
|
+
s.add_development_dependency(%q<pry>, [">= 0"])
|
162
|
+
s.add_development_dependency(%q<fake_dynamo>, [">= 0"])
|
163
|
+
s.add_development_dependency(%q<mocha>, ["= 0.10.0"])
|
164
|
+
else
|
165
|
+
s.add_dependency(%q<activemodel>, [">= 0"])
|
166
|
+
s.add_dependency(%q<tzinfo>, [">= 0"])
|
167
|
+
s.add_dependency(%q<aws-sdk>, [">= 0"])
|
168
|
+
s.add_dependency(%q<rake>, [">= 0"])
|
169
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
170
|
+
s.add_dependency(%q<bundler>, [">= 0"])
|
171
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
172
|
+
s.add_dependency(%q<yard>, [">= 0"])
|
173
|
+
s.add_dependency(%q<redcarpet>, ["= 1.17.2"])
|
174
|
+
s.add_dependency(%q<github-markup>, [">= 0"])
|
175
|
+
s.add_dependency(%q<pry>, [">= 0"])
|
176
|
+
s.add_dependency(%q<fake_dynamo>, [">= 0"])
|
177
|
+
s.add_dependency(%q<mocha>, ["= 0.10.0"])
|
178
|
+
end
|
179
|
+
else
|
180
|
+
s.add_dependency(%q<activemodel>, [">= 0"])
|
181
|
+
s.add_dependency(%q<tzinfo>, [">= 0"])
|
182
|
+
s.add_dependency(%q<aws-sdk>, [">= 0"])
|
183
|
+
s.add_dependency(%q<rake>, [">= 0"])
|
184
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
185
|
+
s.add_dependency(%q<bundler>, [">= 0"])
|
186
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
187
|
+
s.add_dependency(%q<yard>, [">= 0"])
|
188
|
+
s.add_dependency(%q<redcarpet>, ["= 1.17.2"])
|
189
|
+
s.add_dependency(%q<github-markup>, [">= 0"])
|
190
|
+
s.add_dependency(%q<pry>, [">= 0"])
|
191
|
+
s.add_dependency(%q<fake_dynamo>, [">= 0"])
|
192
|
+
s.add_dependency(%q<mocha>, ["= 0.10.0"])
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
data/lib/dynamoid/adapter.rb
CHANGED
@@ -73,7 +73,7 @@ module Dynamoid
|
|
73
73
|
ids = ids.collect{|id| range_key ? [id, range_key] : id}
|
74
74
|
if Dynamoid::Config.partitioning?
|
75
75
|
results = batch_get_item(table => id_with_partitions(ids))
|
76
|
-
{table => result_for_partition(results[table])}
|
76
|
+
{table => result_for_partition(results[table],table)}
|
77
77
|
else
|
78
78
|
batch_get_item(table => ids)
|
79
79
|
end
|
@@ -81,7 +81,7 @@ module Dynamoid
|
|
81
81
|
if Dynamoid::Config.partitioning?
|
82
82
|
ids = range_key ? [[ids, range_key]] : ids
|
83
83
|
results = batch_get_item(table => id_with_partitions(ids))
|
84
|
-
result_for_partition(results[table]).first
|
84
|
+
result_for_partition(results[table],table).first
|
85
85
|
else
|
86
86
|
get_item(table, ids, options)
|
87
87
|
end
|
@@ -91,15 +91,31 @@ module Dynamoid
|
|
91
91
|
# Delete an item from a table. If partitioning is turned on, deletes all partitioned keys as well.
|
92
92
|
#
|
93
93
|
# @param [String] table the name of the table to write the object to
|
94
|
-
# @param [
|
95
|
-
# @param [
|
94
|
+
# @param [Array] ids to delete, can also be a string of just one id
|
95
|
+
# @param [Array] range_key of the record to delete, can also be a string of just one range_key
|
96
96
|
#
|
97
|
-
|
98
|
-
|
99
|
-
if
|
100
|
-
|
97
|
+
def delete(table, ids, options = {})
|
98
|
+
range_key = options[:range_key] #array of range keys that matches the ids passed in
|
99
|
+
if ids.respond_to?(:each)
|
100
|
+
if range_key.respond_to?(:each)
|
101
|
+
#turn ids into array of arrays each element being hash_key, range_key
|
102
|
+
ids = ids.each_with_index.map{|id,i| [id,range_key[i]]}
|
103
|
+
else
|
104
|
+
ids = range_key ? [[ids, range_key]] : ids
|
105
|
+
end
|
106
|
+
|
107
|
+
if Dynamoid::Config.partitioning?
|
108
|
+
batch_delete_item(table => id_with_partitions(ids))
|
109
|
+
else
|
110
|
+
batch_delete_item(table => ids)
|
111
|
+
end
|
101
112
|
else
|
102
|
-
|
113
|
+
if Dynamoid::Config.partitioning?
|
114
|
+
ids = range_key ? [[ids, range_key]] : ids
|
115
|
+
batch_delete_item(table => id_with_partitions(ids))
|
116
|
+
else
|
117
|
+
delete_item(table, ids, options)
|
118
|
+
end
|
103
119
|
end
|
104
120
|
end
|
105
121
|
|
@@ -112,7 +128,7 @@ module Dynamoid
|
|
112
128
|
def scan(table, query, opts = {})
|
113
129
|
if Dynamoid::Config.partitioning?
|
114
130
|
results = benchmark('Scan', table, query) {adapter.scan(table, query, opts)}
|
115
|
-
result_for_partition(results)
|
131
|
+
result_for_partition(results,table)
|
116
132
|
else
|
117
133
|
benchmark('Scan', table, query) {adapter.scan(table, query, opts)}
|
118
134
|
end
|
@@ -141,27 +157,59 @@ module Dynamoid
|
|
141
157
|
def id_with_partitions(ids)
|
142
158
|
Array(ids).collect {|id| (0...Dynamoid::Config.partition_size).collect{|n| id.is_a?(Array) ? ["#{id.first}.#{n}", id.last] : "#{id}.#{n}"}}.flatten(1)
|
143
159
|
end
|
160
|
+
|
161
|
+
#Get original id (hash_key) and partiton number from a hash_key
|
162
|
+
#
|
163
|
+
# @param [String] id the id or hash_key of a record, ex. xxxxx.13
|
164
|
+
#
|
165
|
+
# @return [String,String] original_id and the partition number, ex original_id = xxxxx partition = 13
|
166
|
+
def get_original_id_and_partition id
|
167
|
+
partition = id.split('.').last
|
168
|
+
id = id.split(".#{partition}").first
|
169
|
+
|
170
|
+
return id, partition
|
171
|
+
end
|
144
172
|
|
145
|
-
# Takes an array of results that are partitioned, find the most recently updated
|
173
|
+
# Takes an array of query results that are partitioned, find the most recently updated ones that share an id and range_key, and return only the most recently updated. Compares each result by
|
146
174
|
# their id and updated_at attributes; if the updated_at is the greatest, then it must be the correct result.
|
147
175
|
#
|
148
176
|
# @param [Array] returned partitioned results from a query
|
177
|
+
# @param [String] table_name the name of the table
|
149
178
|
#
|
150
179
|
# @since 0.2.0
|
151
|
-
def result_for_partition(results)
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
180
|
+
def result_for_partition(results, table_name)
|
181
|
+
table = Dynamoid::Adapter::AwsSdk.get_table(table_name)
|
182
|
+
|
183
|
+
if table.range_key
|
184
|
+
range_key_name = table.range_key.name.to_sym
|
185
|
+
|
186
|
+
final_hash = {}
|
187
|
+
|
188
|
+
results.each do |record|
|
189
|
+
test_record = final_hash[record[range_key_name]]
|
158
190
|
|
159
|
-
if
|
160
|
-
|
161
|
-
|
191
|
+
if test_record.nil? || ((record[range_key_name] == test_record[range_key_name]) && (record[:updated_at] > test_record[:updated_at]))
|
192
|
+
#get ride of our partition and put it in the array with the range key
|
193
|
+
record[:id], partition = get_original_id_and_partition record[:id]
|
194
|
+
final_hash[record[range_key_name]] = record
|
162
195
|
end
|
163
196
|
end
|
164
|
-
|
197
|
+
|
198
|
+
return final_hash.values
|
199
|
+
else
|
200
|
+
{}.tap do |hash|
|
201
|
+
Array(results).each do |result|
|
202
|
+
next if result.nil?
|
203
|
+
#Need to find the value of id with out the . and partition number
|
204
|
+
id, partition = get_original_id_and_partition result[:id]
|
205
|
+
|
206
|
+
if !hash[id] || (result[:updated_at] > hash[id][:updated_at])
|
207
|
+
result[:id] = id
|
208
|
+
hash[id] = result
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end.values
|
212
|
+
end
|
165
213
|
end
|
166
214
|
|
167
215
|
# Delegate all methods that aren't defind here to the underlying adapter.
|
@@ -171,7 +219,47 @@ module Dynamoid
|
|
171
219
|
return benchmark(method, *args) {adapter.send(method, *args, &block)} if @adapter.respond_to?(method)
|
172
220
|
super
|
173
221
|
end
|
222
|
+
|
223
|
+
# Query the DynamoDB table. This employs DynamoDB's indexes so is generally faster than scanning, but is
|
224
|
+
# only really useful for range queries, since it can only find by one hash key at once. Only provide
|
225
|
+
# one range key to the hash. If paritioning is on, will run a query for every parition and join the results
|
226
|
+
#
|
227
|
+
# @param [String] table_name the name of the table
|
228
|
+
# @param [Hash] opts the options to query the table with
|
229
|
+
# @option opts [String] :hash_value the value of the hash key to find
|
230
|
+
# @option opts [Range] :range_value find the range key within this range
|
231
|
+
# @option opts [Number] :range_greater_than find range keys greater than this
|
232
|
+
# @option opts [Number] :range_less_than find range keys less than this
|
233
|
+
# @option opts [Number] :range_gte find range keys greater than or equal to this
|
234
|
+
# @option opts [Number] :range_lte find range keys less than or equal to this
|
235
|
+
#
|
236
|
+
# @return [Array] an array of all matching items
|
237
|
+
#
|
238
|
+
def query(table_name, opts = {})
|
239
|
+
|
240
|
+
unless Dynamoid::Config.partitioning?
|
241
|
+
#no paritioning? just pass to the standard query method
|
242
|
+
Dynamoid::Adapter::AwsSdk.query(table_name, opts)
|
243
|
+
else
|
244
|
+
#get all the hash_values that could be possible
|
245
|
+
ids = id_with_partitions(opts[:hash_value])
|
174
246
|
|
175
|
-
|
247
|
+
#lets not overwrite with the original options
|
248
|
+
modified_options = opts.clone
|
249
|
+
results = []
|
250
|
+
|
251
|
+
#loop and query on each of the partition ids
|
252
|
+
ids.each do |id|
|
253
|
+
modified_options[:hash_value] = id
|
254
|
+
|
255
|
+
query_result = Dynamoid::Adapter::AwsSdk.query(table_name, modified_options)
|
256
|
+
query_result = [query_result] if !query_result.is_a?(Array)
|
176
257
|
|
258
|
+
results = results + query_result unless query_result.nil?
|
259
|
+
end
|
260
|
+
|
261
|
+
result_for_partition results, table_name
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
177
265
|
end
|
@@ -54,6 +54,29 @@ module Dynamoid
|
|
54
54
|
end
|
55
55
|
hash
|
56
56
|
end
|
57
|
+
|
58
|
+
# Delete many items at once from DynamoDB. More efficient than delete each item individually.
|
59
|
+
#
|
60
|
+
# @example Delete IDs 1 and 2 from the table testtable
|
61
|
+
# Dynamoid::Adapter::AwsSdk.batch_delete_item('table1' => ['1', '2'])
|
62
|
+
#or
|
63
|
+
# Dynamoid::Adapter::AwsSdk.batch_delete_item('table1' => [['hk1', 'rk2'], ['hk1', 'rk2']]]))
|
64
|
+
#
|
65
|
+
# @param [Hash] options the hash of tables and IDs to delete
|
66
|
+
#
|
67
|
+
# @return nil
|
68
|
+
#
|
69
|
+
def batch_delete_item(options)
|
70
|
+
return nil if options.all?{|k, v| v.empty?}
|
71
|
+
options.each do |t, ids|
|
72
|
+
Array(ids).in_groups_of(25, false) do |group|
|
73
|
+
batch = AWS::DynamoDB::BatchWrite.new(:config => @@connection.config)
|
74
|
+
batch.delete(t,group)
|
75
|
+
batch.process!
|
76
|
+
end
|
77
|
+
end
|
78
|
+
nil
|
79
|
+
end
|
57
80
|
|
58
81
|
# Create a table on DynamoDB. This usually takes a long time to complete.
|
59
82
|
#
|
@@ -111,9 +134,6 @@ module Dynamoid
|
|
111
134
|
# @return [Hash] a hash representing the raw item in DynamoDB
|
112
135
|
#
|
113
136
|
# @since 0.2.0
|
114
|
-
|
115
|
-
|
116
|
-
|
117
137
|
def get_item(table_name, key, options = {})
|
118
138
|
range_key = options.delete(:range_key)
|
119
139
|
table = get_table(table_name)
|
@@ -46,6 +46,63 @@ module Dynamoid #:nodoc:
|
|
46
46
|
def all
|
47
47
|
records
|
48
48
|
end
|
49
|
+
|
50
|
+
# Destroys all the records matching the criteria.
|
51
|
+
#
|
52
|
+
def destroy_all
|
53
|
+
ids = []
|
54
|
+
|
55
|
+
if range?
|
56
|
+
ranges = []
|
57
|
+
Dynamoid::Adapter.query(source.table_name, range_query).collect do |hash|
|
58
|
+
ids << hash[source.hash_key.to_sym]
|
59
|
+
ranges << hash[source.range_key.to_sym]
|
60
|
+
end
|
61
|
+
|
62
|
+
Dynamoid::Adapter.delete(source.table_name, ids,{:range_key => ranges})
|
63
|
+
elsif index
|
64
|
+
#TODO: test this throughly and find a way to delete all index table records for one source record
|
65
|
+
if index.range_key?
|
66
|
+
results = Dynamoid::Adapter.query(index.table_name, index_query.merge(consistent_opts))
|
67
|
+
else
|
68
|
+
results = Dynamoid::Adapter.read(index.table_name, index_query[:hash_value], consistent_opts)
|
69
|
+
end
|
70
|
+
|
71
|
+
results.collect do |hash|
|
72
|
+
ids << hash[source.hash_key.to_sym]
|
73
|
+
index_ranges << hash[source.range_key.to_sym]
|
74
|
+
end
|
75
|
+
|
76
|
+
unless ids.nil? || ids.empty?
|
77
|
+
ids = ids.to_a
|
78
|
+
|
79
|
+
if @start
|
80
|
+
ids = ids.drop_while { |id| id != @start.hash_key }.drop(1)
|
81
|
+
index_ranges = index_ranges.drop_while { |range| range != @start.hash_key }.drop(1) unless index_ranges.nil?
|
82
|
+
end
|
83
|
+
|
84
|
+
if @limit
|
85
|
+
ids = ids.take(@limit)
|
86
|
+
index_ranges = index_ranges.take(@limit)
|
87
|
+
end
|
88
|
+
|
89
|
+
Dynamoid::Adapter.delete(source.table_name, ids)
|
90
|
+
|
91
|
+
if index.range_key?
|
92
|
+
Dynamoid::Adapter.delete(index.table_name, ids,{:range_key => index_ranges})
|
93
|
+
else
|
94
|
+
Dynamoid::Adapter.delete(index.table_name, ids)
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
else
|
99
|
+
Dynamoid::Adapter.scan(source.table_name, query, scan_opts).collect do |hash|
|
100
|
+
ids << hash[source.hash_key.to_sym]
|
101
|
+
end
|
102
|
+
|
103
|
+
Dynamoid::Adapter.delete(source.table_name, ids)
|
104
|
+
end
|
105
|
+
end
|
49
106
|
|
50
107
|
# Returns the first record matching the criteria.
|
51
108
|
#
|
@@ -151,7 +208,7 @@ module Dynamoid #:nodoc:
|
|
151
208
|
raise Dynamoid::Errors::InvalidQuery, 'Consistent read is not supported by SCAN operation'
|
152
209
|
end
|
153
210
|
|
154
|
-
Dynamoid::Adapter.scan(source.table_name, query,
|
211
|
+
Dynamoid::Adapter.scan(source.table_name, query, scan_opts).collect {|hash| source.from_database(hash) }
|
155
212
|
end
|
156
213
|
|
157
214
|
# Format the provided query so that it can be used to query results from DynamoDB.
|
@@ -236,6 +293,13 @@ module Dynamoid #:nodoc:
|
|
236
293
|
opts[:scan_index_forward] = @scan_index_forward
|
237
294
|
opts
|
238
295
|
end
|
296
|
+
|
297
|
+
def scan_opts
|
298
|
+
opts = {}
|
299
|
+
opts[:limit] = @limit if @limit
|
300
|
+
opts[:next_token] = start_key if @start
|
301
|
+
opts
|
302
|
+
end
|
239
303
|
end
|
240
304
|
|
241
305
|
end
|
data/lib/dynamoid/fields.rb
CHANGED
@@ -16,7 +16,7 @@ describe Dynamoid::Adapter::AwsSdk do
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
context 'with a preexisting table' do
|
19
|
+
context 'with a preexisting table without paritioning' do
|
20
20
|
before(:all) do
|
21
21
|
Dynamoid::Adapter.create_table('dynamoid_tests_TestTable1', :id) unless Dynamoid::Adapter.list_tables.include?('dynamoid_tests_TestTable1')
|
22
22
|
Dynamoid::Adapter.create_table('dynamoid_tests_TestTable2', :id) unless Dynamoid::Adapter.list_tables.include?('dynamoid_tests_TestTable2')
|
@@ -99,6 +99,56 @@ describe Dynamoid::Adapter::AwsSdk do
|
|
99
99
|
results['dynamoid_tests_TestTable3'].should include({:name => 'Josh', :id => '1', :range => 1.0})
|
100
100
|
results['dynamoid_tests_TestTable3'].should include({:name => 'Justin', :id => '2', :range => 2.0})
|
101
101
|
end
|
102
|
+
|
103
|
+
# BatchDeleteItem
|
104
|
+
it "performs BatchDeleteItem with singular keys" do
|
105
|
+
Dynamoid::Adapter.put_item('dynamoid_tests_TestTable1', {:id => '1', :name => 'Josh'})
|
106
|
+
Dynamoid::Adapter.put_item('dynamoid_tests_TestTable2', {:id => '1', :name => 'Justin'})
|
107
|
+
|
108
|
+
Dynamoid::Adapter.batch_delete_item('dynamoid_tests_TestTable1' => ['1'], 'dynamoid_tests_TestTable2' => ['1'])
|
109
|
+
|
110
|
+
results = Dynamoid::Adapter.batch_get_item('dynamoid_tests_TestTable1' => '1', 'dynamoid_tests_TestTable2' => '1')
|
111
|
+
results.size.should == 0
|
112
|
+
|
113
|
+
results['dynamoid_tests_TestTable1'].should_not include({:name => 'Josh', :id => '1'})
|
114
|
+
results['dynamoid_tests_TestTable2'].should_not include({:name => 'Justin', :id => '1'})
|
115
|
+
end
|
116
|
+
|
117
|
+
it "performs BatchDeleteItem with multiple keys" do
|
118
|
+
Dynamoid::Adapter.put_item('dynamoid_tests_TestTable1', {:id => '1', :name => 'Josh'})
|
119
|
+
Dynamoid::Adapter.put_item('dynamoid_tests_TestTable1', {:id => '2', :name => 'Justin'})
|
120
|
+
|
121
|
+
Dynamoid::Adapter.batch_delete_item('dynamoid_tests_TestTable1' => ['1', '2'])
|
122
|
+
|
123
|
+
results = Dynamoid::Adapter.batch_get_item('dynamoid_tests_TestTable1' => ['1', '2'])
|
124
|
+
results.size.should == 0
|
125
|
+
|
126
|
+
results['dynamoid_tests_TestTable1'].should_not include({:name => 'Josh', :id => '1'})
|
127
|
+
results['dynamoid_tests_TestTable1'].should_not include({:name => 'Justin', :id => '2'})
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'performs BatchDeleteItem with one ranged key' do
|
131
|
+
Dynamoid::Adapter.put_item('dynamoid_tests_TestTable3', {:id => '1', :name => 'Josh', :range => 1.0})
|
132
|
+
Dynamoid::Adapter.put_item('dynamoid_tests_TestTable3', {:id => '2', :name => 'Justin', :range => 2.0})
|
133
|
+
|
134
|
+
Dynamoid::Adapter.batch_delete_item('dynamoid_tests_TestTable3' => [['1', 1.0]])
|
135
|
+
results = Dynamoid::Adapter.batch_get_item('dynamoid_tests_TestTable3' => [['1', 1.0]])
|
136
|
+
results.size.should == 0
|
137
|
+
|
138
|
+
results['dynamoid_tests_TestTable3'].should_not include({:name => 'Josh', :id => '1', :range => 1.0})
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'performs BatchDeleteItem with multiple ranged keys' do
|
142
|
+
Dynamoid::Adapter.put_item('dynamoid_tests_TestTable3', {:id => '1', :name => 'Josh', :range => 1.0})
|
143
|
+
Dynamoid::Adapter.put_item('dynamoid_tests_TestTable3', {:id => '2', :name => 'Justin', :range => 2.0})
|
144
|
+
|
145
|
+
Dynamoid::Adapter.batch_delete_item('dynamoid_tests_TestTable3' => [['1', 1.0],['2', 2.0]])
|
146
|
+
results = Dynamoid::Adapter.batch_get_item('dynamoid_tests_TestTable3' => [['1', 1.0],['2', 2.0]])
|
147
|
+
results.size.should == 0
|
148
|
+
|
149
|
+
results['dynamoid_tests_TestTable3'].should_not include({:name => 'Josh', :id => '1', :range => 1.0})
|
150
|
+
results['dynamoid_tests_TestTable3'].should_not include({:name => 'Justin', :id => '2', :range => 2.0})
|
151
|
+
end
|
102
152
|
|
103
153
|
# ListTables
|
104
154
|
it 'performs ListTables' do
|
@@ -175,6 +225,90 @@ describe Dynamoid::Adapter::AwsSdk do
|
|
175
225
|
Dynamoid::Adapter.scan('dynamoid_tests_TestTable1', {}).should include({:name=>"Josh", :id=>"2"}, {:name=>"Josh", :id=>"1"})
|
176
226
|
end
|
177
227
|
end
|
228
|
+
|
229
|
+
context 'with a preexisting table with paritioning' do
|
230
|
+
before(:all) do
|
231
|
+
@previous_value = Dynamoid::Config.partitioning
|
232
|
+
Dynamoid::Config.partitioning = true
|
233
|
+
|
234
|
+
Dynamoid::Adapter.create_table('dynamoid_tests_TestTable1', :id) unless Dynamoid::Adapter.list_tables.include?('dynamoid_tests_TestTable1')
|
235
|
+
Dynamoid::Adapter.create_table('dynamoid_tests_TestTable2', :id) unless Dynamoid::Adapter.list_tables.include?('dynamoid_tests_TestTable2')
|
236
|
+
Dynamoid::Adapter.create_table('dynamoid_tests_TestTable3', :id, :range_key => { :range => :number }) unless Dynamoid::Adapter.list_tables.include?('dynamoid_tests_TestTable3')
|
237
|
+
end
|
238
|
+
|
239
|
+
after(:all) do
|
240
|
+
Dynamoid::Config.partitioning = @previous_value
|
241
|
+
end
|
242
|
+
|
243
|
+
# Query
|
244
|
+
it 'performs query on a table and returns items' do
|
245
|
+
Dynamoid::Adapter.put_item('dynamoid_tests_TestTable1', {:id => '1.1', :name => 'Josh'})
|
246
|
+
|
247
|
+
Dynamoid::Adapter.query('dynamoid_tests_TestTable1', :hash_value => '1').first.should == { :id=> '1', :name=>"Josh" }
|
248
|
+
end
|
249
|
+
|
250
|
+
it 'performs query on a table and returns items if there are multiple items' do
|
251
|
+
Dynamoid::Adapter.put_item('dynamoid_tests_TestTable1', {:id => '1.1', :name => 'Josh'})
|
252
|
+
Dynamoid::Adapter.put_item('dynamoid_tests_TestTable1', {:id => '2.1', :name => 'Justin'})
|
253
|
+
|
254
|
+
Dynamoid::Adapter.query('dynamoid_tests_TestTable1', :hash_value => '1').first.should == { :id=> '1', :name=>"Josh" }
|
255
|
+
end
|
256
|
+
|
257
|
+
context 'range queries' do
|
258
|
+
before do
|
259
|
+
Dynamoid::Adapter.put_item('dynamoid_tests_TestTable3', {:id => '1.1', :range => 1.0})
|
260
|
+
Dynamoid::Adapter.put_item('dynamoid_tests_TestTable3', {:id => '1.1', :range => 3.0})
|
261
|
+
end
|
262
|
+
|
263
|
+
it 'performs query on a table with a range and selects items in a range' do
|
264
|
+
Dynamoid::Adapter.query('dynamoid_tests_TestTable3', :hash_value => '1', :range_value => 0.0..3.0).should =~ [{:id => '1', :range => BigDecimal.new(1)}, {:id => '1', :range => BigDecimal.new(3)}]
|
265
|
+
end
|
266
|
+
|
267
|
+
it 'performs query on a table with a range and selects items greater than' do
|
268
|
+
Dynamoid::Adapter.query('dynamoid_tests_TestTable3', :hash_value => '1', :range_greater_than => 1.0).should =~ [{:id => '1', :range => BigDecimal.new(3)}]
|
269
|
+
end
|
270
|
+
|
271
|
+
it 'performs query on a table with a range and selects items less than' do
|
272
|
+
Dynamoid::Adapter.query('dynamoid_tests_TestTable3', :hash_value => '1', :range_less_than => 2.0).should =~ [{:id => '1', :range => BigDecimal.new(1)}]
|
273
|
+
end
|
274
|
+
|
275
|
+
it 'performs query on a table with a range and selects items gte' do
|
276
|
+
Dynamoid::Adapter.query('dynamoid_tests_TestTable3', :hash_value => '1', :range_gte => 1.0).should =~ [{:id => '1', :range => BigDecimal.new(1)}, {:id => '1', :range => BigDecimal.new(3)}]
|
277
|
+
end
|
278
|
+
|
279
|
+
it 'performs query on a table with a range and selects items lte' do
|
280
|
+
Dynamoid::Adapter.query('dynamoid_tests_TestTable3', :hash_value => '1', :range_lte => 3.0).should =~ [{:id => '1', :range => BigDecimal.new(1)}, {:id => '1', :range => BigDecimal.new(3)}]
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
# Scan
|
285
|
+
it 'performs scan on a table and returns items' do
|
286
|
+
Dynamoid::Adapter.put_item('dynamoid_tests_TestTable1', {:id => '1.1', :name => 'Josh'})
|
287
|
+
|
288
|
+
Dynamoid::Adapter.scan('dynamoid_tests_TestTable1', :name => 'Josh').should == [{ :id=> '1', :name=>"Josh" }]
|
289
|
+
end
|
290
|
+
|
291
|
+
it 'performs scan on a table and returns items if there are multiple items but only one match' do
|
292
|
+
Dynamoid::Adapter.put_item('dynamoid_tests_TestTable1', {:id => '1.1', :name => 'Josh'})
|
293
|
+
Dynamoid::Adapter.put_item('dynamoid_tests_TestTable1', {:id => '2.1', :name => 'Justin'})
|
294
|
+
|
295
|
+
Dynamoid::Adapter.scan('dynamoid_tests_TestTable1', :name => 'Josh').should == [{ :id=> '1', :name=>"Josh" }]
|
296
|
+
end
|
297
|
+
|
298
|
+
it 'performs scan on a table and returns multiple items if there are multiple matches' do
|
299
|
+
Dynamoid::Adapter.put_item('dynamoid_tests_TestTable1', {:id => '1.1', :name => 'Josh'})
|
300
|
+
Dynamoid::Adapter.put_item('dynamoid_tests_TestTable1', {:id => '2.1', :name => 'Josh'})
|
301
|
+
|
302
|
+
Dynamoid::Adapter.scan('dynamoid_tests_TestTable1', :name => 'Josh').should include({:name=>"Josh", :id=>"2"}, {:name=>"Josh", :id=>"1"})
|
303
|
+
end
|
304
|
+
|
305
|
+
it 'performs scan on a table and returns all items if no criteria are specified' do
|
306
|
+
Dynamoid::Adapter.put_item('dynamoid_tests_TestTable1', {:id => '1.1', :name => 'Josh'})
|
307
|
+
Dynamoid::Adapter.put_item('dynamoid_tests_TestTable1', {:id => '2.1', :name => 'Josh'})
|
308
|
+
|
309
|
+
Dynamoid::Adapter.scan('dynamoid_tests_TestTable1', {}).should include({:name=>"Josh", :id=>"2"}, {:name=>"Josh", :id=>"1"})
|
310
|
+
end
|
311
|
+
end
|
178
312
|
|
179
313
|
# DescribeTable
|
180
314
|
|
@@ -42,6 +42,18 @@ describe "Dynamoid::Adapter" do
|
|
42
42
|
Dynamoid::Adapter.read('dynamoid_tests_TestTable', ['1', '2'])
|
43
43
|
end
|
44
44
|
|
45
|
+
it 'delete through the adapter for one ID' do
|
46
|
+
Dynamoid::Adapter.expects(:delete_item).with('dynamoid_tests_TestTable', '123', {}).returns(nil)
|
47
|
+
|
48
|
+
Dynamoid::Adapter.delete('dynamoid_tests_TestTable', '123')
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'deletes through the adapter for many IDs' do
|
52
|
+
Dynamoid::Adapter.expects(:batch_delete_item).with({'dynamoid_tests_TestTable' => ['1', '2']}).returns(nil)
|
53
|
+
|
54
|
+
Dynamoid::Adapter.delete('dynamoid_tests_TestTable', ['1', '2'])
|
55
|
+
end
|
56
|
+
|
45
57
|
it 'reads through the adapter for one ID and a range key' do
|
46
58
|
Dynamoid::Adapter.expects(:get_item).with('dynamoid_tests_TestTable', '123', :range_key => 2.0).returns(true)
|
47
59
|
|
@@ -53,6 +65,18 @@ describe "Dynamoid::Adapter" do
|
|
53
65
|
|
54
66
|
Dynamoid::Adapter.read('dynamoid_tests_TestTable', ['1', '2'], :range_key => 2.0)
|
55
67
|
end
|
68
|
+
|
69
|
+
it 'deletes through the adapter for one ID and a range key' do
|
70
|
+
Dynamoid::Adapter.expects(:delete_item).with('dynamoid_tests_TestTable', '123', :range_key => 2.0).returns(nil)
|
71
|
+
|
72
|
+
Dynamoid::Adapter.delete('dynamoid_tests_TestTable', '123', :range_key => 2.0)
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'deletes through the adapter for many IDs and a range key' do
|
76
|
+
Dynamoid::Adapter.expects(:batch_delete_item).with({'dynamoid_tests_TestTable' => [['1', 2.0], ['2', 2.0]]}).returns(nil)
|
77
|
+
|
78
|
+
Dynamoid::Adapter.delete('dynamoid_tests_TestTable', ['1', '2'], :range_key => [2.0,2.0])
|
79
|
+
end
|
56
80
|
end
|
57
81
|
|
58
82
|
context 'with partitioning' do
|
@@ -109,9 +133,38 @@ describe "Dynamoid::Adapter" do
|
|
109
133
|
@time = DateTime.now
|
110
134
|
@array =[{:id => '1.0', :updated_at => @time - 6.hours}, {:id => '1.1', :updated_at => @time - 3.hours}, {:id => '1.2', :updated_at => @time - 1.hour}, {:id => '1.3', :updated_at => @time - 6.hours}, {:id => '2.0', :updated_at => @time}]
|
111
135
|
|
112
|
-
Dynamoid::Adapter.result_for_partition(@array).should =~ [{:id => '1', :updated_at => @time - 1.hour}, {:id => '2', :updated_at => @time}]
|
136
|
+
Dynamoid::Adapter.result_for_partition(@array,"dynamoid_tests_TestTable").should =~ [{:id => '1', :updated_at => @time - 1.hour}, {:id => '2', :updated_at => @time}]
|
113
137
|
end
|
114
138
|
|
139
|
+
it 'returns a valid original id and partition number' do
|
140
|
+
@id = "12345.387327.-sdf3"
|
141
|
+
@partition_number = "4"
|
142
|
+
Dynamoid::Adapter.get_original_id_and_partition("#{@id}.#{@partition_number}").should == [@id, @partition_number]
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'delete through the adapter for one ID' do
|
146
|
+
Dynamoid::Adapter.expects(:batch_delete_item).with('dynamoid_tests_TestTable' => (0...Dynamoid::Config.partition_size).collect{|n| "123.#{n}"}).returns(nil)
|
147
|
+
|
148
|
+
Dynamoid::Adapter.delete('dynamoid_tests_TestTable', '123')
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'deletes through the adapter for many IDs' do
|
152
|
+
Dynamoid::Adapter.expects(:batch_delete_item).with('dynamoid_tests_TestTable' => (0...Dynamoid::Config.partition_size).collect{|n| "1.#{n}"} + (0...Dynamoid::Config.partition_size).collect{|n| "2.#{n}"}).returns(nil)
|
153
|
+
|
154
|
+
Dynamoid::Adapter.delete('dynamoid_tests_TestTable', ['1', '2'])
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'deletes through the adapter for one ID and a range key' do
|
158
|
+
Dynamoid::Adapter.expects(:batch_delete_item).with('dynamoid_tests_TestTable' => (0...Dynamoid::Config.partition_size).collect{|n| ["123.#{n}", 2.0]}).returns(nil)
|
159
|
+
|
160
|
+
Dynamoid::Adapter.delete('dynamoid_tests_TestTable', '123', :range_key => 2.0)
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'deletes through the adapter for many IDs and a range key' do
|
164
|
+
Dynamoid::Adapter.expects(:batch_delete_item).with('dynamoid_tests_TestTable' => (0...Dynamoid::Config.partition_size).collect{|n| ["1.#{n}", 2.0]} + (0...Dynamoid::Config.partition_size).collect{|n| ["2.#{n}", 2.0]}).returns(nil)
|
165
|
+
|
166
|
+
Dynamoid::Adapter.delete('dynamoid_tests_TestTable', ['1', '2'], :range_key => [2.0,2.0])
|
167
|
+
end
|
115
168
|
end
|
116
169
|
|
117
170
|
end
|
@@ -136,5 +136,29 @@ describe "Dynamoid::Associations::Chain" do
|
|
136
136
|
@chain.send(:records_with_range).should == [@tweet3]
|
137
137
|
end
|
138
138
|
end
|
139
|
+
|
140
|
+
context 'destroy alls' do
|
141
|
+
before do
|
142
|
+
@tweet1 = Tweet.create(:tweet_id => "x", :group => "one")
|
143
|
+
@tweet2 = Tweet.create(:tweet_id => "x", :group => "two")
|
144
|
+
@tweet3 = Tweet.create(:tweet_id => "xx", :group => "two")
|
145
|
+
@chain = Dynamoid::Criteria::Chain.new(Tweet)
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'destroys tweet with a range simple range query' do
|
149
|
+
@chain.query = { :tweet_id => "x" }
|
150
|
+
@chain.all.size.should == 2
|
151
|
+
@chain.destroy_all
|
152
|
+
@chain.consistent.all.size.should == 0
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'deletes one specific tweet with range' do
|
156
|
+
@chain = Dynamoid::Criteria::Chain.new(Tweet)
|
157
|
+
@chain.query = { :tweet_id => "xx", :group => "two" }
|
158
|
+
@chain.all.size.should == 1
|
159
|
+
@chain.destroy_all
|
160
|
+
@chain.consistent.all.size.should == 0
|
161
|
+
end
|
162
|
+
end
|
139
163
|
|
140
164
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: adept_dynamoid
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-12-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activemodel
|
@@ -240,6 +240,7 @@ files:
|
|
240
240
|
- README.markdown
|
241
241
|
- Rakefile
|
242
242
|
- VERSION
|
243
|
+
- adept_dynamoid.gemspec
|
243
244
|
- doc/.nojekyll
|
244
245
|
- doc/Dynamoid.html
|
245
246
|
- doc/Dynamoid/Adapter.html
|
@@ -362,6 +363,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
362
363
|
- - ! '>='
|
363
364
|
- !ruby/object:Gem::Version
|
364
365
|
version: '0'
|
366
|
+
segments:
|
367
|
+
- 0
|
368
|
+
hash: 108672444036973826
|
365
369
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
366
370
|
none: false
|
367
371
|
requirements:
|
@@ -375,4 +379,3 @@ signing_key:
|
|
375
379
|
specification_version: 3
|
376
380
|
summary: Dynamoid is an ORM for Amazon's DynamoDB
|
377
381
|
test_files: []
|
378
|
-
has_rdoc:
|