dynamoid 0.6.1 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +4 -0
- data/Gemfile +3 -2
- data/Gemfile.lock +40 -45
- data/README.markdown +55 -25
- data/Rakefile +31 -0
- data/VERSION +1 -1
- data/doc/Dynamoid.html +58 -42
- data/doc/Dynamoid/Adapter.html +666 -179
- data/doc/Dynamoid/Adapter/AwsSdk.html +752 -236
- data/doc/Dynamoid/Associations.html +28 -21
- data/doc/Dynamoid/Associations/Association.html +102 -49
- data/doc/Dynamoid/Associations/BelongsTo.html +28 -25
- data/doc/Dynamoid/Associations/ClassMethods.html +95 -52
- data/doc/Dynamoid/Associations/HasAndBelongsToMany.html +28 -25
- data/doc/Dynamoid/Associations/HasMany.html +28 -25
- data/doc/Dynamoid/Associations/HasOne.html +28 -25
- data/doc/Dynamoid/Associations/ManyAssociation.html +138 -94
- data/doc/Dynamoid/Associations/SingleAssociation.html +67 -38
- data/doc/Dynamoid/Components.html +60 -22
- data/doc/Dynamoid/Config.html +61 -44
- data/doc/Dynamoid/Config/Options.html +90 -61
- data/doc/Dynamoid/Criteria.html +28 -21
- data/doc/Dynamoid/Criteria/Chain.html +508 -100
- data/doc/Dynamoid/Criteria/ClassMethods.html +26 -19
- data/doc/Dynamoid/Dirty.html +424 -0
- data/doc/Dynamoid/Dirty/ClassMethods.html +174 -0
- data/doc/Dynamoid/Document.html +451 -84
- data/doc/Dynamoid/Document/ClassMethods.html +281 -102
- data/doc/Dynamoid/Errors.html +29 -22
- data/doc/Dynamoid/Errors/ConditionalCheckFailedException.html +141 -0
- data/doc/Dynamoid/Errors/DocumentNotValid.html +36 -25
- data/doc/Dynamoid/Errors/Error.html +27 -20
- data/doc/Dynamoid/Errors/InvalidField.html +27 -19
- data/doc/Dynamoid/Errors/InvalidQuery.html +131 -0
- data/doc/Dynamoid/Errors/MissingRangeKey.html +27 -19
- data/doc/Dynamoid/Fields.html +94 -77
- data/doc/Dynamoid/Fields/ClassMethods.html +166 -37
- data/doc/Dynamoid/Finders.html +28 -21
- data/doc/Dynamoid/Finders/ClassMethods.html +505 -78
- data/doc/Dynamoid/IdentityMap.html +492 -0
- data/doc/Dynamoid/IdentityMap/ClassMethods.html +534 -0
- data/doc/Dynamoid/Indexes.html +41 -28
- data/doc/Dynamoid/Indexes/ClassMethods.html +45 -29
- data/doc/Dynamoid/Indexes/Index.html +100 -62
- data/doc/Dynamoid/Middleware.html +115 -0
- data/doc/Dynamoid/Middleware/IdentityMap.html +264 -0
- data/doc/Dynamoid/Persistence.html +326 -85
- data/doc/Dynamoid/Persistence/ClassMethods.html +275 -109
- data/doc/Dynamoid/Validations.html +47 -31
- data/doc/_index.html +116 -71
- data/doc/class_list.html +13 -7
- data/doc/css/full_list.css +4 -2
- data/doc/css/style.css +60 -44
- data/doc/file.LICENSE.html +26 -19
- data/doc/file.README.html +152 -48
- data/doc/file_list.html +14 -8
- data/doc/frames.html +20 -5
- data/doc/index.html +152 -48
- data/doc/js/app.js +52 -43
- data/doc/js/full_list.js +14 -9
- data/doc/js/jquery.js +4 -16
- data/doc/method_list.html +446 -540
- data/doc/top-level-namespace.html +27 -20
- data/{Dynamoid.gemspec → dynamoid.gemspec} +21 -8
- data/lib/dynamoid/adapter.rb +11 -10
- data/lib/dynamoid/adapter/aws_sdk.rb +40 -19
- data/lib/dynamoid/components.rb +2 -1
- data/lib/dynamoid/criteria/chain.rb +29 -11
- data/lib/dynamoid/dirty.rb +6 -0
- data/lib/dynamoid/document.rb +34 -19
- data/lib/dynamoid/fields.rb +36 -30
- data/lib/dynamoid/finders.rb +7 -5
- data/lib/dynamoid/persistence.rb +37 -10
- data/spec/app/models/address.rb +2 -0
- data/spec/app/models/camel_case.rb +10 -0
- data/spec/app/models/car.rb +6 -0
- data/spec/app/models/nuclear_submarine.rb +5 -0
- data/spec/app/models/subscription.rb +2 -2
- data/spec/app/models/vehicle.rb +7 -0
- data/spec/dynamoid/adapter/aws_sdk_spec.rb +20 -11
- data/spec/dynamoid/adapter_spec.rb +67 -82
- data/spec/dynamoid/associations/association_spec.rb +30 -30
- data/spec/dynamoid/criteria/chain_spec.rb +56 -9
- data/spec/dynamoid/criteria_spec.rb +3 -0
- data/spec/dynamoid/dirty_spec.rb +8 -0
- data/spec/dynamoid/document_spec.rb +109 -47
- data/spec/dynamoid/fields_spec.rb +32 -3
- data/spec/dynamoid/finders_spec.rb +12 -0
- data/spec/dynamoid/persistence_spec.rb +73 -8
- data/spec/spec_helper.rb +1 -0
- data/spec/support/with_partitioning.rb +15 -0
- metadata +22 -9
@@ -6,19 +6,21 @@
|
|
6
6
|
<title>
|
7
7
|
Top Level Namespace
|
8
8
|
|
9
|
-
— Documentation by YARD 0.
|
9
|
+
— Documentation by YARD 0.8.6.1
|
10
10
|
|
11
11
|
</title>
|
12
12
|
|
13
|
-
<link rel="stylesheet" href="css/style.css" type="text/css"
|
13
|
+
<link rel="stylesheet" href="css/style.css" type="text/css" charset="utf-8" />
|
14
14
|
|
15
|
-
<link rel="stylesheet" href="css/common.css" type="text/css"
|
15
|
+
<link rel="stylesheet" href="css/common.css" type="text/css" charset="utf-8" />
|
16
16
|
|
17
17
|
<script type="text/javascript" charset="utf-8">
|
18
|
+
hasFrames = window.top.frames.main ? true : false;
|
18
19
|
relpath = '';
|
19
|
-
|
20
|
+
framesUrl = "frames.html#!" + escape(window.location.href);
|
20
21
|
</script>
|
21
22
|
|
23
|
+
|
22
24
|
<script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
|
23
25
|
|
24
26
|
<script type="text/javascript" charset="utf-8" src="js/app.js"></script>
|
@@ -26,36 +28,41 @@
|
|
26
28
|
|
27
29
|
</head>
|
28
30
|
<body>
|
29
|
-
<script type="text/javascript" charset="utf-8">
|
30
|
-
if (window.top.frames.main) document.body.className = 'frames';
|
31
|
-
</script>
|
32
|
-
|
33
31
|
<div id="header">
|
34
32
|
<div id="menu">
|
35
33
|
|
36
|
-
<a href="_index.html">Index</a> »
|
34
|
+
<a href="_index.html">Index</a> »
|
37
35
|
|
38
36
|
|
39
37
|
<span class="title">Top Level Namespace</span>
|
40
38
|
|
41
|
-
|
39
|
+
|
42
40
|
<div class="noframes"><span class="title">(</span><a href="." target="_top">no frames</a><span class="title">)</span></div>
|
43
41
|
</div>
|
44
42
|
|
45
43
|
<div id="search">
|
46
44
|
|
47
|
-
<a
|
45
|
+
<a class="full_list_link" id="class_list_link"
|
46
|
+
href="class_list.html">
|
47
|
+
Class List
|
48
|
+
</a>
|
48
49
|
|
49
|
-
<a
|
50
|
+
<a class="full_list_link" id="method_list_link"
|
51
|
+
href="method_list.html">
|
52
|
+
Method List
|
53
|
+
</a>
|
50
54
|
|
51
|
-
<a
|
55
|
+
<a class="full_list_link" id="file_list_link"
|
56
|
+
href="file_list.html">
|
57
|
+
File List
|
58
|
+
</a>
|
52
59
|
|
53
60
|
</div>
|
54
61
|
<div class="clear"></div>
|
55
62
|
</div>
|
56
|
-
|
63
|
+
|
57
64
|
<iframe id="search_frame"></iframe>
|
58
|
-
|
65
|
+
|
59
66
|
<div id="content"><h1>Top Level Namespace
|
60
67
|
|
61
68
|
|
@@ -76,11 +83,11 @@
|
|
76
83
|
|
77
84
|
<h2>Defined Under Namespace</h2>
|
78
85
|
<p class="children">
|
79
|
-
|
86
|
+
|
80
87
|
|
81
88
|
<strong class="modules">Modules:</strong> <span class='object_link'><a href="Dynamoid.html" title="Dynamoid (module)">Dynamoid</a></span>
|
82
89
|
|
83
|
-
|
90
|
+
|
84
91
|
|
85
92
|
|
86
93
|
</p>
|
@@ -94,11 +101,11 @@
|
|
94
101
|
|
95
102
|
|
96
103
|
</div>
|
97
|
-
|
104
|
+
|
98
105
|
<div id="footer">
|
99
|
-
Generated on Thu
|
106
|
+
Generated on Thu Jun 27 21:59:09 2013 by
|
100
107
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
101
|
-
0.
|
108
|
+
0.8.6.1 (ruby-1.9.3).
|
102
109
|
</div>
|
103
110
|
|
104
111
|
</body>
|
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "dynamoid"
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.7.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Josh Symonds"]
|
12
|
-
s.date = "2013-
|
12
|
+
s.date = "2013-06-28"
|
13
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."
|
14
14
|
s.email = "josh@joshsymonds.com"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.files = [
|
20
20
|
".document",
|
21
21
|
".rspec",
|
22
|
-
"
|
22
|
+
".travis.yml",
|
23
23
|
"Gemfile",
|
24
24
|
"Gemfile.lock",
|
25
25
|
"LICENSE.txt",
|
@@ -46,20 +46,28 @@ Gem::Specification.new do |s|
|
|
46
46
|
"doc/Dynamoid/Criteria.html",
|
47
47
|
"doc/Dynamoid/Criteria/Chain.html",
|
48
48
|
"doc/Dynamoid/Criteria/ClassMethods.html",
|
49
|
+
"doc/Dynamoid/Dirty.html",
|
50
|
+
"doc/Dynamoid/Dirty/ClassMethods.html",
|
49
51
|
"doc/Dynamoid/Document.html",
|
50
52
|
"doc/Dynamoid/Document/ClassMethods.html",
|
51
53
|
"doc/Dynamoid/Errors.html",
|
54
|
+
"doc/Dynamoid/Errors/ConditionalCheckFailedException.html",
|
52
55
|
"doc/Dynamoid/Errors/DocumentNotValid.html",
|
53
56
|
"doc/Dynamoid/Errors/Error.html",
|
54
57
|
"doc/Dynamoid/Errors/InvalidField.html",
|
58
|
+
"doc/Dynamoid/Errors/InvalidQuery.html",
|
55
59
|
"doc/Dynamoid/Errors/MissingRangeKey.html",
|
56
60
|
"doc/Dynamoid/Fields.html",
|
57
61
|
"doc/Dynamoid/Fields/ClassMethods.html",
|
58
62
|
"doc/Dynamoid/Finders.html",
|
59
63
|
"doc/Dynamoid/Finders/ClassMethods.html",
|
64
|
+
"doc/Dynamoid/IdentityMap.html",
|
65
|
+
"doc/Dynamoid/IdentityMap/ClassMethods.html",
|
60
66
|
"doc/Dynamoid/Indexes.html",
|
61
67
|
"doc/Dynamoid/Indexes/ClassMethods.html",
|
62
68
|
"doc/Dynamoid/Indexes/Index.html",
|
69
|
+
"doc/Dynamoid/Middleware.html",
|
70
|
+
"doc/Dynamoid/Middleware/IdentityMap.html",
|
63
71
|
"doc/Dynamoid/Persistence.html",
|
64
72
|
"doc/Dynamoid/Persistence/ClassMethods.html",
|
65
73
|
"doc/Dynamoid/Validations.html",
|
@@ -78,6 +86,7 @@ Gem::Specification.new do |s|
|
|
78
86
|
"doc/js/jquery.js",
|
79
87
|
"doc/method_list.html",
|
80
88
|
"doc/top-level-namespace.html",
|
89
|
+
"dynamoid.gemspec",
|
81
90
|
"lib/dynamoid.rb",
|
82
91
|
"lib/dynamoid/adapter.rb",
|
83
92
|
"lib/dynamoid/adapter/aws_sdk.rb",
|
@@ -107,12 +116,15 @@ Gem::Specification.new do |s|
|
|
107
116
|
"lib/dynamoid/validations.rb",
|
108
117
|
"spec/app/models/address.rb",
|
109
118
|
"spec/app/models/camel_case.rb",
|
119
|
+
"spec/app/models/car.rb",
|
110
120
|
"spec/app/models/magazine.rb",
|
111
121
|
"spec/app/models/message.rb",
|
122
|
+
"spec/app/models/nuclear_submarine.rb",
|
112
123
|
"spec/app/models/sponsor.rb",
|
113
124
|
"spec/app/models/subscription.rb",
|
114
125
|
"spec/app/models/tweet.rb",
|
115
126
|
"spec/app/models/user.rb",
|
127
|
+
"spec/app/models/vehicle.rb",
|
116
128
|
"spec/dynamoid/adapter/aws_sdk_spec.rb",
|
117
129
|
"spec/dynamoid/adapter_spec.rb",
|
118
130
|
"spec/dynamoid/associations/association_spec.rb",
|
@@ -134,12 +146,13 @@ Gem::Specification.new do |s|
|
|
134
146
|
"spec/dynamoid/persistence_spec.rb",
|
135
147
|
"spec/dynamoid/validations_spec.rb",
|
136
148
|
"spec/dynamoid_spec.rb",
|
137
|
-
"spec/spec_helper.rb"
|
149
|
+
"spec/spec_helper.rb",
|
150
|
+
"spec/support/with_partitioning.rb"
|
138
151
|
]
|
139
152
|
s.homepage = "http://github.com/Veraticus/Dynamoid"
|
140
153
|
s.licenses = ["MIT"]
|
141
154
|
s.require_paths = ["lib"]
|
142
|
-
s.rubygems_version = "1.8.
|
155
|
+
s.rubygems_version = "1.8.25"
|
143
156
|
s.summary = "Dynamoid is an ORM for Amazon's DynamoDB"
|
144
157
|
|
145
158
|
if s.respond_to? :specification_version then
|
@@ -157,7 +170,7 @@ Gem::Specification.new do |s|
|
|
157
170
|
s.add_development_dependency(%q<redcarpet>, ["= 1.17.2"])
|
158
171
|
s.add_development_dependency(%q<github-markup>, [">= 0"])
|
159
172
|
s.add_development_dependency(%q<pry>, [">= 0"])
|
160
|
-
s.add_development_dependency(%q<fake_dynamo>, ["
|
173
|
+
s.add_development_dependency(%q<fake_dynamo>, ["~> 0.1.3"])
|
161
174
|
s.add_development_dependency(%q<mocha>, ["= 0.10.0"])
|
162
175
|
else
|
163
176
|
s.add_dependency(%q<activemodel>, [">= 0"])
|
@@ -171,7 +184,7 @@ Gem::Specification.new do |s|
|
|
171
184
|
s.add_dependency(%q<redcarpet>, ["= 1.17.2"])
|
172
185
|
s.add_dependency(%q<github-markup>, [">= 0"])
|
173
186
|
s.add_dependency(%q<pry>, [">= 0"])
|
174
|
-
s.add_dependency(%q<fake_dynamo>, ["
|
187
|
+
s.add_dependency(%q<fake_dynamo>, ["~> 0.1.3"])
|
175
188
|
s.add_dependency(%q<mocha>, ["= 0.10.0"])
|
176
189
|
end
|
177
190
|
else
|
@@ -186,7 +199,7 @@ Gem::Specification.new do |s|
|
|
186
199
|
s.add_dependency(%q<redcarpet>, ["= 1.17.2"])
|
187
200
|
s.add_dependency(%q<github-markup>, [">= 0"])
|
188
201
|
s.add_dependency(%q<pry>, [">= 0"])
|
189
|
-
s.add_dependency(%q<fake_dynamo>, ["
|
202
|
+
s.add_dependency(%q<fake_dynamo>, ["~> 0.1.3"])
|
190
203
|
s.add_dependency(%q<mocha>, ["= 0.10.0"])
|
191
204
|
end
|
192
205
|
end
|
data/lib/dynamoid/adapter.rb
CHANGED
@@ -65,25 +65,28 @@ module Dynamoid
|
|
65
65
|
#
|
66
66
|
# @param [String] table the name of the table to write the object to
|
67
67
|
# @param [Array] ids to fetch, can also be a string of just one id
|
68
|
-
# @param [
|
68
|
+
# @param [Hash] options: Passed to the underlying query. The :range_key option is required whenever the table has a range key,
|
69
|
+
# unless multiple ids are passed in and Dynamoid::Config.partitioning? is turned off.
|
69
70
|
#
|
70
71
|
# @since 0.2.0
|
71
72
|
def read(table, ids, options = {})
|
72
|
-
range_key = options
|
73
|
+
range_key = options.delete(:range_key)
|
74
|
+
|
73
75
|
if ids.respond_to?(:each)
|
74
76
|
ids = ids.collect{|id| range_key ? [id, range_key] : id}
|
75
77
|
if Dynamoid::Config.partitioning?
|
76
|
-
results = batch_get_item(table => id_with_partitions(ids))
|
78
|
+
results = batch_get_item({table => id_with_partitions(ids)}, options)
|
77
79
|
{table => result_for_partition(results[table],table)}
|
78
80
|
else
|
79
|
-
batch_get_item(table => ids)
|
81
|
+
batch_get_item({table => ids}, options)
|
80
82
|
end
|
81
83
|
else
|
82
84
|
if Dynamoid::Config.partitioning?
|
83
85
|
ids = range_key ? [[ids, range_key]] : ids
|
84
|
-
results = batch_get_item(table => id_with_partitions(ids))
|
86
|
+
results = batch_get_item({table => id_with_partitions(ids)}, options)
|
85
87
|
result_for_partition(results[table],table).first
|
86
88
|
else
|
89
|
+
options[:range_key] = range_key if range_key
|
87
90
|
get_item(table, ids, options)
|
88
91
|
end
|
89
92
|
end
|
@@ -185,7 +188,7 @@ module Dynamoid
|
|
185
188
|
range_key_name = table.range_key.name.to_sym
|
186
189
|
|
187
190
|
final_hash = {}
|
188
|
-
|
191
|
+
|
189
192
|
results.each do |record|
|
190
193
|
test_record = final_hash[record[range_key_name]]
|
191
194
|
|
@@ -254,11 +257,9 @@ module Dynamoid
|
|
254
257
|
modified_options[:hash_value] = id
|
255
258
|
|
256
259
|
query_result = Dynamoid::Adapter::AwsSdk.query(table_name, modified_options)
|
257
|
-
query_result
|
258
|
-
|
259
|
-
results = results + query_result unless query_result.nil?
|
260
|
+
results += query_result.inject([]){|array, result| array += [result]} if query_result.any?
|
260
261
|
end
|
261
|
-
|
262
|
+
|
262
263
|
result_for_partition results, table_name
|
263
264
|
end
|
264
265
|
end
|
@@ -53,20 +53,21 @@ module Dynamoid
|
|
53
53
|
# Get many items at once from DynamoDB. More efficient than getting each item individually.
|
54
54
|
#
|
55
55
|
# @example Retrieve IDs 1 and 2 from the table testtable
|
56
|
-
# Dynamoid::Adapter::AwsSdk.batch_get_item('table1' => ['1', '2'])
|
56
|
+
# Dynamoid::Adapter::AwsSdk.batch_get_item({'table1' => ['1', '2']}, :consistent_read => true)
|
57
57
|
#
|
58
|
-
# @param [Hash]
|
58
|
+
# @param [Hash] table_ids the hash of tables and IDs to retrieve
|
59
|
+
# @param [Hash] options to be passed to underlying BatchGet call
|
59
60
|
#
|
60
61
|
# @return [Hash] a hash where keys are the table names and the values are the retrieved items
|
61
62
|
#
|
62
63
|
# @since 0.2.0
|
63
|
-
def batch_get_item(options)
|
64
|
+
def batch_get_item(table_ids, options = {})
|
64
65
|
hash = Hash.new{|h, k| h[k] = []}
|
65
|
-
return hash if
|
66
|
-
|
66
|
+
return hash if table_ids.all?{|k, v| v.empty?}
|
67
|
+
table_ids.each do |t, ids|
|
67
68
|
Array(ids).in_groups_of(100, false) do |group|
|
68
69
|
batch = AWS::DynamoDB::BatchGet.new(:config => @@connection.config)
|
69
|
-
batch.table(t, :all, Array(group)) unless group.nil? || group.empty?
|
70
|
+
batch.table(t, :all, Array(group), options) unless group.nil? || group.empty?
|
70
71
|
batch.each do |table_name, attributes|
|
71
72
|
hash[table_name] << attributes.symbolize_keys!
|
72
73
|
end
|
@@ -196,6 +197,8 @@ module Dynamoid
|
|
196
197
|
object.delete_if{|k, v| v.nil? || (v.respond_to?(:empty?) && v.empty?)},
|
197
198
|
options || {}
|
198
199
|
)
|
200
|
+
rescue AWS::DynamoDB::Errors::ConditionalCheckFailedException => e
|
201
|
+
raise Dynamoid::Errors::ConditionalCheckFailedException
|
199
202
|
end
|
200
203
|
|
201
204
|
# Query the DynamoDB table. This employs DynamoDB's indexes so is generally faster than scanning, but is
|
@@ -211,19 +214,25 @@ module Dynamoid
|
|
211
214
|
# @option opts [Number] :range_gte find range keys greater than or equal to this
|
212
215
|
# @option opts [Number] :range_lte find range keys less than or equal to this
|
213
216
|
#
|
214
|
-
# @return [
|
217
|
+
# @return [Enumerator] an iterator of all matching items
|
215
218
|
#
|
216
219
|
# @since 0.2.0
|
217
220
|
def query(table_name, opts = {})
|
218
221
|
table = get_table(table_name)
|
219
222
|
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
223
|
+
Enumerator.new do |yielder|
|
224
|
+
consistent_opts = { :consistent_read => opts[:consistent_read] || false }
|
225
|
+
if table.composite_key?
|
226
|
+
table.items.query(opts).each do |data|
|
227
|
+
if opts.has_key? :select
|
228
|
+
yielder.yield data.attributes.symbolize_keys!
|
229
|
+
else
|
230
|
+
yielder.yield data.attributes.to_h(consistent_opts).symbolize_keys!
|
231
|
+
end
|
232
|
+
end
|
233
|
+
else
|
234
|
+
yielder.yield get_item(table_name, opts[:hash_value])
|
235
|
+
end
|
227
236
|
end
|
228
237
|
end
|
229
238
|
|
@@ -233,16 +242,16 @@ module Dynamoid
|
|
233
242
|
# @param [String] table_name the name of the table
|
234
243
|
# @param [Hash] scan_hash a hash of attributes: matching records will be returned by the scan
|
235
244
|
#
|
236
|
-
# @return [
|
245
|
+
# @return [Enumerator] an iterator of all matching items
|
237
246
|
#
|
238
247
|
# @since 0.2.0
|
239
248
|
def scan(table_name, scan_hash, select_opts)
|
240
249
|
table = get_table(table_name)
|
241
|
-
|
242
|
-
|
243
|
-
|
250
|
+
Enumerator.new do |yielder|
|
251
|
+
table.items.where(scan_hash).select(select_opts).each do |data|
|
252
|
+
yielder.yield data.attributes.symbolize_keys!
|
253
|
+
end
|
244
254
|
end
|
245
|
-
results
|
246
255
|
end
|
247
256
|
|
248
257
|
# @todo Add an UpdateItem method.
|
@@ -261,6 +270,18 @@ module Dynamoid
|
|
261
270
|
def table_cache
|
262
271
|
@table_cache ||= {}
|
263
272
|
end
|
273
|
+
|
274
|
+
# Number of items from a table
|
275
|
+
#
|
276
|
+
# @param [String] table_name the name of the table
|
277
|
+
#
|
278
|
+
# @return [Integer] the number of items from a table
|
279
|
+
#
|
280
|
+
# @since 0.6.1
|
281
|
+
def count(table_name)
|
282
|
+
table = get_table(table_name)
|
283
|
+
table.items.count
|
284
|
+
end
|
264
285
|
end
|
265
286
|
end
|
266
287
|
end
|
data/lib/dynamoid/components.rb
CHANGED
@@ -10,10 +10,11 @@ module Dynamoid
|
|
10
10
|
extend ActiveModel::Translation
|
11
11
|
extend ActiveModel::Callbacks
|
12
12
|
|
13
|
-
define_model_callbacks :create, :save, :destroy, :initialize
|
13
|
+
define_model_callbacks :create, :save, :destroy, :initialize, :update
|
14
14
|
|
15
15
|
before_create :set_created_at
|
16
16
|
before_save :set_updated_at
|
17
|
+
after_initialize :set_type
|
17
18
|
end
|
18
19
|
|
19
20
|
include ActiveModel::AttributeMethods
|
@@ -31,7 +31,7 @@ module Dynamoid #:nodoc:
|
|
31
31
|
#
|
32
32
|
# @since 0.2.0
|
33
33
|
def where(args)
|
34
|
-
args.each {|k, v| query[k] = v}
|
34
|
+
args.each {|k, v| query[k.to_sym] = v}
|
35
35
|
self
|
36
36
|
end
|
37
37
|
|
@@ -43,7 +43,8 @@ module Dynamoid #:nodoc:
|
|
43
43
|
# Returns all the records matching the criteria.
|
44
44
|
#
|
45
45
|
# @since 0.2.0
|
46
|
-
def all
|
46
|
+
def all(opts = {})
|
47
|
+
batch opts[:batch_size] if opts.has_key? :batch_size
|
47
48
|
records
|
48
49
|
end
|
49
50
|
|
@@ -116,6 +117,12 @@ module Dynamoid #:nodoc:
|
|
116
117
|
records
|
117
118
|
end
|
118
119
|
|
120
|
+
def batch(batch_size)
|
121
|
+
raise 'Cannot batch calls when using partitioning' if Dynamoid::Config.partitioning?
|
122
|
+
@batch_size = batch_size
|
123
|
+
self
|
124
|
+
end
|
125
|
+
|
119
126
|
def start(start)
|
120
127
|
@start = start
|
121
128
|
self
|
@@ -141,28 +148,29 @@ module Dynamoid #:nodoc:
|
|
141
148
|
|
142
149
|
# The actual records referenced by the association.
|
143
150
|
#
|
144
|
-
# @return [
|
151
|
+
# @return [Enumerator] an iterator of the found records.
|
145
152
|
#
|
146
153
|
# @since 0.2.0
|
147
154
|
def records
|
148
|
-
if range?
|
155
|
+
results = if range?
|
149
156
|
records_with_range
|
150
157
|
elsif index
|
151
158
|
records_with_index
|
152
159
|
else
|
153
160
|
records_without_index
|
154
161
|
end
|
162
|
+
@batch_size ? results : Array(results)
|
155
163
|
end
|
156
164
|
|
157
165
|
# If the query matches an index on the associated class, then this method will retrieve results from the index table.
|
158
166
|
#
|
159
|
-
# @return [
|
167
|
+
# @return [Enumerator] an iterator of the found records.
|
160
168
|
#
|
161
169
|
# @since 0.2.0
|
162
170
|
def records_with_index
|
163
171
|
ids = ids_from_index
|
164
172
|
if ids.nil? || ids.empty?
|
165
|
-
[]
|
173
|
+
Enumerator.new []
|
166
174
|
else
|
167
175
|
ids = ids.to_a
|
168
176
|
|
@@ -171,7 +179,7 @@ module Dynamoid #:nodoc:
|
|
171
179
|
end
|
172
180
|
|
173
181
|
ids = ids.take(@limit) if @limit
|
174
|
-
|
182
|
+
source.find(ids, consistent_opts)
|
175
183
|
end
|
176
184
|
end
|
177
185
|
|
@@ -190,12 +198,16 @@ module Dynamoid #:nodoc:
|
|
190
198
|
end
|
191
199
|
|
192
200
|
def records_with_range
|
193
|
-
|
201
|
+
Enumerator.new do |yielder|
|
202
|
+
Dynamoid::Adapter.query(source.table_name, range_query).each do |hash|
|
203
|
+
yielder.yield source.from_database(hash)
|
204
|
+
end
|
205
|
+
end
|
194
206
|
end
|
195
207
|
|
196
208
|
# If the query does not match an index, we'll manually scan the associated table to find results.
|
197
209
|
#
|
198
|
-
# @return [
|
210
|
+
# @return [Enumerator] an iterator of the found records.
|
199
211
|
#
|
200
212
|
# @since 0.2.0
|
201
213
|
def records_without_index
|
@@ -208,7 +220,11 @@ module Dynamoid #:nodoc:
|
|
208
220
|
raise Dynamoid::Errors::InvalidQuery, 'Consistent read is not supported by SCAN operation'
|
209
221
|
end
|
210
222
|
|
211
|
-
|
223
|
+
Enumerator.new do |yielder|
|
224
|
+
Dynamoid::Adapter.scan(source.table_name, query, scan_opts).each do |hash|
|
225
|
+
yielder.yield source.from_database(hash)
|
226
|
+
end
|
227
|
+
end
|
212
228
|
end
|
213
229
|
|
214
230
|
# Format the provided query so that it can be used to query results from DynamoDB.
|
@@ -271,8 +287,9 @@ module Dynamoid #:nodoc:
|
|
271
287
|
query.keys.collect{|k| k.to_s.split('.').first}
|
272
288
|
end
|
273
289
|
|
290
|
+
# Use range query only when [hash_key] or [hash_key, range_key] is specified in query keys.
|
274
291
|
def range?
|
275
|
-
return false unless source.range_key
|
292
|
+
return false unless query_keys.include?(source.hash_key.to_s) or query_keys.include?(source.range_key.to_s)
|
276
293
|
query_keys == [source.hash_key.to_s] || (query_keys.to_set == [source.hash_key.to_s, source.range_key.to_s].to_set)
|
277
294
|
end
|
278
295
|
|
@@ -298,6 +315,7 @@ module Dynamoid #:nodoc:
|
|
298
315
|
opts = {}
|
299
316
|
opts[:limit] = @limit if @limit
|
300
317
|
opts[:next_token] = start_key if @start
|
318
|
+
opts[:batch_size] = @batch_size if @batch_size
|
301
319
|
opts
|
302
320
|
end
|
303
321
|
end
|