dynamoid 0.7.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +2 -24
- data/README.markdown +89 -73
- data/Rakefile +10 -36
- data/dynamoid.gemspec +56 -191
- data/lib/dynamoid.rb +6 -4
- data/lib/dynamoid/adapter.rb +64 -150
- data/lib/dynamoid/adapter_plugin/aws_sdk_v2.rb +579 -0
- data/lib/dynamoid/components.rb +0 -1
- data/lib/dynamoid/config.rb +2 -5
- data/lib/dynamoid/criteria.rb +1 -1
- data/lib/dynamoid/criteria/chain.rb +27 -140
- data/lib/dynamoid/document.rb +2 -2
- data/lib/dynamoid/errors.rb +30 -9
- data/lib/dynamoid/fields.rb +15 -3
- data/lib/dynamoid/finders.rb +7 -6
- data/lib/dynamoid/identity_map.rb +1 -5
- data/lib/dynamoid/persistence.rb +108 -93
- metadata +56 -229
- data/.document +0 -5
- data/.rspec +0 -1
- data/.travis.yml +0 -7
- data/Gemfile.lock +0 -81
- data/Gemfile_activemodel4 +0 -24
- data/Gemfile_activemodel4.lock +0 -88
- data/VERSION +0 -1
- data/doc/.nojekyll +0 -0
- data/doc/Dynamoid.html +0 -328
- data/doc/Dynamoid/Adapter.html +0 -1872
- data/doc/Dynamoid/Adapter/AwsSdk.html +0 -2101
- data/doc/Dynamoid/Adapter/Local.html +0 -1574
- data/doc/Dynamoid/Associations.html +0 -138
- data/doc/Dynamoid/Associations/Association.html +0 -847
- data/doc/Dynamoid/Associations/BelongsTo.html +0 -161
- data/doc/Dynamoid/Associations/ClassMethods.html +0 -766
- data/doc/Dynamoid/Associations/HasAndBelongsToMany.html +0 -167
- data/doc/Dynamoid/Associations/HasMany.html +0 -167
- data/doc/Dynamoid/Associations/HasOne.html +0 -161
- data/doc/Dynamoid/Associations/ManyAssociation.html +0 -1684
- data/doc/Dynamoid/Associations/SingleAssociation.html +0 -627
- data/doc/Dynamoid/Components.html +0 -242
- data/doc/Dynamoid/Config.html +0 -412
- data/doc/Dynamoid/Config/Options.html +0 -638
- data/doc/Dynamoid/Criteria.html +0 -138
- data/doc/Dynamoid/Criteria/Chain.html +0 -1471
- data/doc/Dynamoid/Criteria/ClassMethods.html +0 -105
- data/doc/Dynamoid/Dirty.html +0 -424
- data/doc/Dynamoid/Dirty/ClassMethods.html +0 -174
- data/doc/Dynamoid/Document.html +0 -1033
- data/doc/Dynamoid/Document/ClassMethods.html +0 -1116
- data/doc/Dynamoid/Errors.html +0 -125
- data/doc/Dynamoid/Errors/ConditionalCheckFailedException.html +0 -141
- data/doc/Dynamoid/Errors/DocumentNotValid.html +0 -221
- data/doc/Dynamoid/Errors/Error.html +0 -137
- data/doc/Dynamoid/Errors/InvalidField.html +0 -141
- data/doc/Dynamoid/Errors/InvalidQuery.html +0 -131
- data/doc/Dynamoid/Errors/MissingRangeKey.html +0 -141
- data/doc/Dynamoid/Fields.html +0 -686
- data/doc/Dynamoid/Fields/ClassMethods.html +0 -438
- data/doc/Dynamoid/Finders.html +0 -135
- data/doc/Dynamoid/Finders/ClassMethods.html +0 -943
- data/doc/Dynamoid/IdentityMap.html +0 -492
- data/doc/Dynamoid/IdentityMap/ClassMethods.html +0 -534
- data/doc/Dynamoid/Indexes.html +0 -321
- data/doc/Dynamoid/Indexes/ClassMethods.html +0 -369
- data/doc/Dynamoid/Indexes/Index.html +0 -1142
- data/doc/Dynamoid/Middleware.html +0 -115
- data/doc/Dynamoid/Middleware/IdentityMap.html +0 -264
- data/doc/Dynamoid/Persistence.html +0 -892
- data/doc/Dynamoid/Persistence/ClassMethods.html +0 -836
- data/doc/Dynamoid/Validations.html +0 -415
- data/doc/_index.html +0 -506
- data/doc/class_list.html +0 -53
- data/doc/css/common.css +0 -1
- data/doc/css/full_list.css +0 -57
- data/doc/css/style.css +0 -338
- data/doc/file.LICENSE.html +0 -73
- data/doc/file.README.html +0 -416
- data/doc/file_list.html +0 -58
- data/doc/frames.html +0 -28
- data/doc/index.html +0 -416
- data/doc/js/app.js +0 -214
- data/doc/js/full_list.js +0 -178
- data/doc/js/jquery.js +0 -4
- data/doc/method_list.html +0 -1144
- data/doc/top-level-namespace.html +0 -112
- data/lib/dynamoid/adapter/aws_sdk.rb +0 -287
- data/lib/dynamoid/indexes.rb +0 -69
- data/lib/dynamoid/indexes/index.rb +0 -103
- data/spec/app/models/address.rb +0 -13
- data/spec/app/models/camel_case.rb +0 -34
- data/spec/app/models/car.rb +0 -6
- data/spec/app/models/magazine.rb +0 -11
- data/spec/app/models/message.rb +0 -9
- data/spec/app/models/nuclear_submarine.rb +0 -5
- data/spec/app/models/sponsor.rb +0 -8
- data/spec/app/models/subscription.rb +0 -12
- data/spec/app/models/tweet.rb +0 -12
- data/spec/app/models/user.rb +0 -26
- data/spec/app/models/vehicle.rb +0 -7
- data/spec/dynamoid/adapter/aws_sdk_spec.rb +0 -376
- data/spec/dynamoid/adapter_spec.rb +0 -155
- data/spec/dynamoid/associations/association_spec.rb +0 -194
- data/spec/dynamoid/associations/belongs_to_spec.rb +0 -71
- data/spec/dynamoid/associations/has_and_belongs_to_many_spec.rb +0 -47
- data/spec/dynamoid/associations/has_many_spec.rb +0 -42
- data/spec/dynamoid/associations/has_one_spec.rb +0 -45
- data/spec/dynamoid/associations_spec.rb +0 -16
- data/spec/dynamoid/config_spec.rb +0 -27
- data/spec/dynamoid/criteria/chain_spec.rb +0 -210
- data/spec/dynamoid/criteria_spec.rb +0 -75
- data/spec/dynamoid/dirty_spec.rb +0 -57
- data/spec/dynamoid/document_spec.rb +0 -180
- data/spec/dynamoid/fields_spec.rb +0 -156
- data/spec/dynamoid/finders_spec.rb +0 -147
- data/spec/dynamoid/identity_map_spec.rb +0 -45
- data/spec/dynamoid/indexes/index_spec.rb +0 -104
- data/spec/dynamoid/indexes_spec.rb +0 -25
- data/spec/dynamoid/persistence_spec.rb +0 -301
- data/spec/dynamoid/validations_spec.rb +0 -36
- data/spec/dynamoid_spec.rb +0 -9
- data/spec/spec_helper.rb +0 -55
- data/spec/support/with_partitioning.rb +0 -15
data/lib/dynamoid/components.rb
CHANGED
data/lib/dynamoid/config.rb
CHANGED
@@ -11,7 +11,7 @@ module Dynamoid
|
|
11
11
|
include ActiveModel::Observing if defined?(ActiveModel::Observing)
|
12
12
|
|
13
13
|
# All the default options.
|
14
|
-
option :adapter, :default => '
|
14
|
+
option :adapter, :default => 'aws_sdk_v2'
|
15
15
|
option :namespace, :default => defined?(Rails) ? "dynamoid_#{Rails.application.class.parent_name}_#{Rails.env}" : "dynamoid"
|
16
16
|
option :logger, :default => defined?(Rails)
|
17
17
|
option :access_key
|
@@ -19,12 +19,9 @@ module Dynamoid
|
|
19
19
|
option :read_capacity, :default => 100
|
20
20
|
option :write_capacity, :default => 20
|
21
21
|
option :warn_on_scan, :default => true
|
22
|
-
option :
|
23
|
-
option :partition_size, :default => 200
|
24
|
-
option :endpoint, :default => 'dynamodb.us-east-1.amazonaws.com'
|
22
|
+
option :endpoint, :default => nil
|
25
23
|
option :use_ssl, :default => true
|
26
24
|
option :port, :default => '443'
|
27
|
-
option :included_models, :default => []
|
28
25
|
option :identity_map, :default => false
|
29
26
|
|
30
27
|
# The default logger for Dynamoid: either the Rails logger or just stdout.
|
data/lib/dynamoid/criteria.rb
CHANGED
@@ -9,7 +9,7 @@ module Dynamoid
|
|
9
9
|
|
10
10
|
module ClassMethods
|
11
11
|
|
12
|
-
[:where, :all, :first, :each, :
|
12
|
+
[:where, :all, :first, :each, :eval_limit, :start, :scan_index_forward].each do |meth|
|
13
13
|
# Return a criteria chain in response to a method that will begin or end a chain. For more information,
|
14
14
|
# see Dynamoid::Criteria::Chain.
|
15
15
|
#
|
@@ -3,10 +3,9 @@ module Dynamoid #:nodoc:
|
|
3
3
|
module Criteria
|
4
4
|
|
5
5
|
# The criteria chain is equivalent to an ActiveRecord relation (and realistically I should change the name from
|
6
|
-
# chain to relation). It is a chainable object that builds up a query and eventually executes it
|
7
|
-
# or by a full table scan.
|
6
|
+
# chain to relation). It is a chainable object that builds up a query and eventually executes it by a Query or Scan.
|
8
7
|
class Chain
|
9
|
-
attr_accessor :query, :source, :
|
8
|
+
attr_accessor :query, :source, :values, :consistent_read
|
10
9
|
include Enumerable
|
11
10
|
|
12
11
|
# Create a new criteria chain.
|
@@ -43,82 +42,38 @@ module Dynamoid #:nodoc:
|
|
43
42
|
# Returns all the records matching the criteria.
|
44
43
|
#
|
45
44
|
# @since 0.2.0
|
46
|
-
def all
|
47
|
-
batch opts[:batch_size] if opts.has_key? :batch_size
|
45
|
+
def all
|
48
46
|
records
|
49
47
|
end
|
50
|
-
|
48
|
+
|
51
49
|
# Destroys all the records matching the criteria.
|
52
50
|
#
|
53
51
|
def destroy_all
|
54
52
|
ids = []
|
55
53
|
|
56
|
-
if
|
54
|
+
if key_present?
|
57
55
|
ranges = []
|
58
|
-
Dynamoid
|
56
|
+
Dynamoid.adapter.query(source.table_name, range_query).collect do |hash|
|
59
57
|
ids << hash[source.hash_key.to_sym]
|
60
58
|
ranges << hash[source.range_key.to_sym]
|
61
59
|
end
|
62
60
|
|
63
|
-
Dynamoid
|
64
|
-
elsif index
|
65
|
-
#TODO: test this throughly and find a way to delete all index table records for one source record
|
66
|
-
if index.range_key?
|
67
|
-
results = Dynamoid::Adapter.query(index.table_name, index_query.merge(consistent_opts))
|
68
|
-
else
|
69
|
-
results = Dynamoid::Adapter.read(index.table_name, index_query[:hash_value], consistent_opts)
|
70
|
-
end
|
71
|
-
|
72
|
-
results.collect do |hash|
|
73
|
-
ids << hash[source.hash_key.to_sym]
|
74
|
-
index_ranges << hash[source.range_key.to_sym]
|
75
|
-
end
|
76
|
-
|
77
|
-
unless ids.nil? || ids.empty?
|
78
|
-
ids = ids.to_a
|
79
|
-
|
80
|
-
if @start
|
81
|
-
ids = ids.drop_while { |id| id != @start.hash_key }.drop(1)
|
82
|
-
index_ranges = index_ranges.drop_while { |range| range != @start.hash_key }.drop(1) unless index_ranges.nil?
|
83
|
-
end
|
84
|
-
|
85
|
-
if @limit
|
86
|
-
ids = ids.take(@limit)
|
87
|
-
index_ranges = index_ranges.take(@limit)
|
88
|
-
end
|
89
|
-
|
90
|
-
Dynamoid::Adapter.delete(source.table_name, ids)
|
91
|
-
|
92
|
-
if index.range_key?
|
93
|
-
Dynamoid::Adapter.delete(index.table_name, ids,{:range_key => index_ranges})
|
94
|
-
else
|
95
|
-
Dynamoid::Adapter.delete(index.table_name, ids)
|
96
|
-
end
|
97
|
-
|
98
|
-
end
|
61
|
+
Dynamoid.adapter.delete(source.table_name, ids,{:range_key => ranges})
|
99
62
|
else
|
100
|
-
Dynamoid
|
63
|
+
Dynamoid.adapter.scan(source.table_name, query, scan_opts).collect do |hash|
|
101
64
|
ids << hash[source.hash_key.to_sym]
|
102
65
|
end
|
103
66
|
|
104
|
-
Dynamoid
|
67
|
+
Dynamoid.adapter.delete(source.table_name, ids)
|
105
68
|
end
|
106
69
|
end
|
107
70
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
def first
|
112
|
-
limit(1).first
|
113
|
-
end
|
114
|
-
|
115
|
-
def limit(limit)
|
116
|
-
@limit = limit
|
117
|
-
records
|
71
|
+
def eval_limit(limit)
|
72
|
+
@eval_limit = limit
|
73
|
+
self
|
118
74
|
end
|
119
75
|
|
120
76
|
def batch(batch_size)
|
121
|
-
raise 'Cannot batch calls when using partitioning' if Dynamoid::Config.partitioning?
|
122
77
|
@batch_size = batch_size
|
123
78
|
self
|
124
79
|
end
|
@@ -152,54 +107,17 @@ module Dynamoid #:nodoc:
|
|
152
107
|
#
|
153
108
|
# @since 0.2.0
|
154
109
|
def records
|
155
|
-
results = if
|
156
|
-
|
157
|
-
elsif index
|
158
|
-
records_with_index
|
110
|
+
results = if key_present?
|
111
|
+
records_via_query
|
159
112
|
else
|
160
|
-
|
113
|
+
records_via_scan
|
161
114
|
end
|
162
115
|
@batch_size ? results : Array(results)
|
163
116
|
end
|
164
117
|
|
165
|
-
|
166
|
-
#
|
167
|
-
# @return [Enumerator] an iterator of the found records.
|
168
|
-
#
|
169
|
-
# @since 0.2.0
|
170
|
-
def records_with_index
|
171
|
-
ids = ids_from_index
|
172
|
-
if ids.nil? || ids.empty?
|
173
|
-
Enumerator.new []
|
174
|
-
else
|
175
|
-
ids = ids.to_a
|
176
|
-
|
177
|
-
if @start
|
178
|
-
ids = ids.drop_while { |id| id != @start.hash_key }.drop(1)
|
179
|
-
end
|
180
|
-
|
181
|
-
ids = ids.take(@limit) if @limit
|
182
|
-
source.find(ids, consistent_opts)
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
# Returns the Set of IDs from the index table.
|
187
|
-
#
|
188
|
-
# @return [Set] a Set containing the IDs from the index.
|
189
|
-
def ids_from_index
|
190
|
-
if index.range_key?
|
191
|
-
Dynamoid::Adapter.query(index.table_name, index_query.merge(consistent_opts)).inject(Set.new) do |all, record|
|
192
|
-
all + Set.new(record[:ids])
|
193
|
-
end
|
194
|
-
else
|
195
|
-
results = Dynamoid::Adapter.read(index.table_name, index_query[:hash_value], consistent_opts)
|
196
|
-
results ? results[:ids] : []
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
|
-
def records_with_range
|
118
|
+
def records_via_query
|
201
119
|
Enumerator.new do |yielder|
|
202
|
-
Dynamoid
|
120
|
+
Dynamoid.adapter.query(source.table_name, range_query).each do |hash|
|
203
121
|
yielder.yield source.from_database(hash)
|
204
122
|
end
|
205
123
|
end
|
@@ -210,7 +128,7 @@ module Dynamoid #:nodoc:
|
|
210
128
|
# @return [Enumerator] an iterator of the found records.
|
211
129
|
#
|
212
130
|
# @since 0.2.0
|
213
|
-
def
|
131
|
+
def records_via_scan
|
214
132
|
if Dynamoid::Config.warn_on_scan
|
215
133
|
Dynamoid.logger.warn 'Queries without an index are forced to use scan and are generally much slower than indexed queries!'
|
216
134
|
Dynamoid.logger.warn "You can index this query by adding this to #{source.to_s.downcase}.rb: index [#{source.attributes.sort.collect{|attr| ":#{attr}"}.join(', ')}]"
|
@@ -221,38 +139,18 @@ module Dynamoid #:nodoc:
|
|
221
139
|
end
|
222
140
|
|
223
141
|
Enumerator.new do |yielder|
|
224
|
-
Dynamoid
|
142
|
+
Dynamoid.adapter.scan(source.table_name, query, scan_opts).each do |hash|
|
225
143
|
yielder.yield source.from_database(hash)
|
226
144
|
end
|
227
145
|
end
|
228
146
|
end
|
229
147
|
|
230
|
-
# Format the provided query so that it can be used to query results from DynamoDB.
|
231
|
-
#
|
232
|
-
# @return [Hash] a hash with keys of :hash_value and :range_value
|
233
|
-
#
|
234
|
-
# @since 0.2.0
|
235
|
-
def index_query
|
236
|
-
values = index.values(query)
|
237
|
-
{}.tap do |hash|
|
238
|
-
hash[:hash_value] = values[:hash_value]
|
239
|
-
if index.range_key?
|
240
|
-
key = query.keys.find{|k| k.to_s.include?('.')}
|
241
|
-
if key
|
242
|
-
hash.merge!(range_hash(key))
|
243
|
-
else
|
244
|
-
raise Dynamoid::Errors::MissingRangeKey, 'This index requires a range key'
|
245
|
-
end
|
246
|
-
end
|
247
|
-
end
|
248
|
-
end
|
249
|
-
|
250
148
|
def range_hash(key)
|
251
149
|
val = query[key]
|
252
150
|
|
253
151
|
return { :range_value => query[key] } if query[key].is_a?(Range)
|
254
152
|
|
255
|
-
case key.split('.').last
|
153
|
+
case key.to_s.split('.').last
|
256
154
|
when 'gt'
|
257
155
|
{ :range_greater_than => val.to_f }
|
258
156
|
when 'lt'
|
@@ -274,38 +172,27 @@ module Dynamoid #:nodoc:
|
|
274
172
|
opts.merge(query_opts).merge(consistent_opts)
|
275
173
|
end
|
276
174
|
|
277
|
-
# Return an index that fulfills all the attributes the criteria is querying, or nil if none is found.
|
278
|
-
#
|
279
|
-
# @since 0.2.0
|
280
|
-
def index
|
281
|
-
index = source.find_index(query_keys)
|
282
|
-
return nil if index.blank?
|
283
|
-
index
|
284
|
-
end
|
285
|
-
|
286
175
|
def query_keys
|
287
176
|
query.keys.collect{|k| k.to_s.split('.').first}
|
288
177
|
end
|
289
178
|
|
290
|
-
#
|
291
|
-
def
|
292
|
-
return false unless query_keys.include?(source.hash_key.to_s) or query_keys.include?(source.range_key.to_s)
|
179
|
+
# [hash_key] or [hash_key, range_key] is specified in query keys.
|
180
|
+
def key_present?
|
293
181
|
query_keys == [source.hash_key.to_s] || (query_keys.to_set == [source.hash_key.to_s, source.range_key.to_s].to_set)
|
294
182
|
end
|
295
183
|
|
296
184
|
def start_key
|
297
|
-
|
298
|
-
key = { :hash_key_element => { hash_key_type => @start.hash_key.to_s } }
|
185
|
+
key = { :hash_key_element => @start.hash_key }
|
299
186
|
if range_key = @start.class.range_key
|
300
|
-
|
301
|
-
key.merge!({:range_key_element => { range_key_type => @start.send(range_key).to_s } })
|
187
|
+
key.merge!({:range_key_element => @start.send(range_key) })
|
302
188
|
end
|
303
189
|
key
|
304
190
|
end
|
305
191
|
|
306
192
|
def query_opts
|
307
193
|
opts = {}
|
308
|
-
opts[:
|
194
|
+
opts[:select] = 'ALL_ATTRIBUTES'
|
195
|
+
opts[:limit] = @eval_limit if @eval_limit
|
309
196
|
opts[:next_token] = start_key if @start
|
310
197
|
opts[:scan_index_forward] = @scan_index_forward
|
311
198
|
opts
|
@@ -313,7 +200,7 @@ module Dynamoid #:nodoc:
|
|
313
200
|
|
314
201
|
def scan_opts
|
315
202
|
opts = {}
|
316
|
-
opts[:limit] = @
|
203
|
+
opts[:limit] = @eval_limit if @eval_limit
|
317
204
|
opts[:next_token] = start_key if @start
|
318
205
|
opts[:batch_size] = @batch_size if @batch_size
|
319
206
|
opts
|
data/lib/dynamoid/document.rb
CHANGED
@@ -13,7 +13,7 @@ module Dynamoid #:nodoc:
|
|
13
13
|
self.read_only_attributes = []
|
14
14
|
self.base_class = self
|
15
15
|
|
16
|
-
Dynamoid
|
16
|
+
Dynamoid.included_models << self
|
17
17
|
end
|
18
18
|
|
19
19
|
module ClassMethods
|
@@ -61,7 +61,7 @@ module Dynamoid #:nodoc:
|
|
61
61
|
#
|
62
62
|
# @since 0.6.1
|
63
63
|
def count
|
64
|
-
Dynamoid
|
64
|
+
Dynamoid.adapter.count(table_name)
|
65
65
|
end
|
66
66
|
|
67
67
|
# Initialize a new object and immediately save it to the database.
|
data/lib/dynamoid/errors.rb
CHANGED
@@ -1,22 +1,43 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
module Dynamoid
|
3
3
|
|
4
|
-
# All the
|
4
|
+
# All the errors specific to Dynamoid. The goal is to mimic ActiveRecord.
|
5
5
|
module Errors
|
6
6
|
|
7
|
-
# Generic error
|
7
|
+
# Generic Dynamoid error
|
8
8
|
class Error < StandardError; end
|
9
9
|
|
10
|
-
# InvalidField is raised when an attribute is specified for an index, but the attribute does not exist.
|
11
|
-
class InvalidField < Error; end
|
12
|
-
|
13
|
-
# MissingRangeKey is raised when a table that requires a range key is quieried without one.
|
14
10
|
class MissingRangeKey < Error; end
|
15
11
|
|
16
|
-
#
|
17
|
-
class ConditionalCheckFailedException < Error
|
12
|
+
# This class is intended to be private to Dynamoid.
|
13
|
+
class ConditionalCheckFailedException < Error
|
14
|
+
attr_reader :inner_exception
|
15
|
+
|
16
|
+
def initialize(inner)
|
17
|
+
super
|
18
|
+
@inner_exception = inner
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class RecordNotUnique < ConditionalCheckFailedException
|
23
|
+
attr_reader :original_exception
|
24
|
+
|
25
|
+
def initialize(original_exception, record)
|
26
|
+
super("Attempted to write record #{record} when its key already exists")
|
27
|
+
@original_exception = original_exception
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class StaleObjectError < ConditionalCheckFailedException
|
32
|
+
attr_reader :record, :attempted_action
|
33
|
+
|
34
|
+
def initialize(record, attempted_action)
|
35
|
+
super("Attempted to #{attempted_action} a stale object #{record}")
|
36
|
+
@record = record
|
37
|
+
@attempted_action = attempted_action
|
38
|
+
end
|
39
|
+
end
|
18
40
|
|
19
|
-
# DocumentNotValid is raised when the document fails validation.
|
20
41
|
class DocumentNotValid < Error
|
21
42
|
def initialize(document)
|
22
43
|
super("Validation failed: #{document.errors.full_messages.join(", ")}")
|
data/lib/dynamoid/fields.rb
CHANGED
@@ -20,16 +20,28 @@ module Dynamoid #:nodoc:
|
|
20
20
|
|
21
21
|
module ClassMethods
|
22
22
|
|
23
|
-
# Specify a field for a document.
|
24
|
-
#
|
23
|
+
# Specify a field for a document.
|
24
|
+
#
|
25
|
+
# Its type determines how it is coerced when read in and out of the datastore.
|
26
|
+
# You can specify :integer, :number, :set, :array, :datetime, and :serialized,
|
27
|
+
# or specify a class that defines a serialization strategy.
|
28
|
+
#
|
29
|
+
# If you specify a class for field type, Dynamoid will serialize using
|
30
|
+
# `dynamoid_dump` or `dump` methods, and load using `dynamoid_load` or `load` methods.
|
31
|
+
#
|
32
|
+
# Default field type is :string.
|
25
33
|
#
|
26
34
|
# @param [Symbol] name the name of the field
|
27
|
-
# @param [Symbol] type the type of the field (
|
35
|
+
# @param [Symbol] type the type of the field (refer to method description for details)
|
28
36
|
# @param [Hash] options any additional options for the field
|
29
37
|
#
|
30
38
|
# @since 0.2.0
|
31
39
|
def field(name, type = :string, options = {})
|
32
40
|
named = name.to_s
|
41
|
+
if type == :float
|
42
|
+
Dynamoid.logger.warn("Field type :float, which you declared for '#{name}', is deprecated in favor of :number.")
|
43
|
+
type = :number
|
44
|
+
end
|
33
45
|
self.attributes = attributes.merge(name => {:type => type}.merge(options))
|
34
46
|
|
35
47
|
define_method(named) { read_attribute(named) }
|
data/lib/dynamoid/finders.rb
CHANGED
@@ -16,16 +16,17 @@ module Dynamoid
|
|
16
16
|
#
|
17
17
|
# @since 0.2.0
|
18
18
|
def find(*ids)
|
19
|
-
|
20
19
|
options = if ids.last.is_a? Hash
|
21
20
|
ids.slice!(-1)
|
22
21
|
else
|
23
22
|
{}
|
24
23
|
end
|
24
|
+
expects_array = ids.first.kind_of?(Array)
|
25
25
|
|
26
26
|
ids = Array(ids.flatten.uniq)
|
27
27
|
if ids.count == 1
|
28
|
-
self.find_by_id(ids.first, options)
|
28
|
+
result = self.find_by_id(ids.first, options)
|
29
|
+
expects_array ? Array(result) : result
|
29
30
|
else
|
30
31
|
find_all(ids)
|
31
32
|
end
|
@@ -44,7 +45,7 @@ module Dynamoid
|
|
44
45
|
# find all the tweets using hash key and range key with consistent read
|
45
46
|
# Tweet.find_all([['1', 'red'], ['1', 'green']], :consistent_read => true)
|
46
47
|
def find_all(ids, options = {})
|
47
|
-
items = Dynamoid
|
48
|
+
items = Dynamoid.adapter.read(self.table_name, ids, options)
|
48
49
|
items ? items[self.table_name].map{|i| from_database(i)} : []
|
49
50
|
end
|
50
51
|
|
@@ -56,7 +57,7 @@ module Dynamoid
|
|
56
57
|
#
|
57
58
|
# @since 0.2.0
|
58
59
|
def find_by_id(id, options = {})
|
59
|
-
if item = Dynamoid
|
60
|
+
if item = Dynamoid.adapter.read(self.table_name, id, options)
|
60
61
|
from_database(item)
|
61
62
|
else
|
62
63
|
nil
|
@@ -66,7 +67,7 @@ module Dynamoid
|
|
66
67
|
# Find one object directly by hash and range keys
|
67
68
|
#
|
68
69
|
# @param [String] hash_key of the object to find
|
69
|
-
# @param [String/
|
70
|
+
# @param [String/Number] range_key of the object to find
|
70
71
|
#
|
71
72
|
def find_by_composite_key(hash_key, range_key, options = {})
|
72
73
|
find_by_id(hash_key, options.merge({:range_key => range_key}))
|
@@ -94,7 +95,7 @@ module Dynamoid
|
|
94
95
|
# @return [Array] an array of all matching items
|
95
96
|
#
|
96
97
|
def find_all_by_composite_key(hash_key, options = {})
|
97
|
-
Dynamoid
|
98
|
+
Dynamoid.adapter.query(self.table_name, options.merge({hash_value: hash_key})).collect do |item|
|
98
99
|
from_database(item)
|
99
100
|
end
|
100
101
|
end
|