aws-sdk 1.2.6 → 1.3.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.
Files changed (60) hide show
  1. data/lib/aws.rb +2 -0
  2. data/lib/aws/api_config/DynamoDB-2011-12-05.yml +721 -0
  3. data/lib/aws/core.rb +10 -1
  4. data/lib/aws/core/client.rb +17 -12
  5. data/lib/aws/core/configuration.rb +13 -3
  6. data/lib/aws/core/configured_json_client_methods.rb +71 -0
  7. data/lib/aws/core/lazy_error_classes.rb +7 -2
  8. data/lib/aws/core/option_grammar.rb +67 -13
  9. data/lib/aws/core/resource.rb +9 -1
  10. data/lib/aws/core/session_signer.rb +95 -0
  11. data/lib/aws/dynamo_db.rb +169 -0
  12. data/lib/aws/dynamo_db/attribute_collection.rb +460 -0
  13. data/lib/aws/dynamo_db/batch_get.rb +206 -0
  14. data/lib/aws/dynamo_db/client.rb +119 -0
  15. data/lib/aws/dynamo_db/config.rb +20 -0
  16. data/lib/aws/dynamo_db/errors.rb +57 -0
  17. data/lib/aws/dynamo_db/expectations.rb +40 -0
  18. data/lib/aws/dynamo_db/item.rb +130 -0
  19. data/lib/aws/dynamo_db/item_collection.rb +837 -0
  20. data/lib/aws/{record/optimistic_locking.rb → dynamo_db/item_data.rb} +9 -12
  21. data/lib/aws/{record/attributes/boolean.rb → dynamo_db/keys.rb} +15 -23
  22. data/lib/aws/dynamo_db/primary_key_element.rb +47 -0
  23. data/lib/aws/dynamo_db/request.rb +78 -0
  24. data/lib/aws/{record/attributes/float.rb → dynamo_db/resource.rb} +10 -25
  25. data/lib/aws/dynamo_db/table.rb +418 -0
  26. data/lib/aws/dynamo_db/table_collection.rb +165 -0
  27. data/lib/aws/dynamo_db/types.rb +86 -0
  28. data/lib/aws/ec2/resource_tag_collection.rb +3 -1
  29. data/lib/aws/record.rb +36 -8
  30. data/lib/aws/record/abstract_base.rb +642 -0
  31. data/lib/aws/record/attributes.rb +384 -0
  32. data/lib/aws/record/dirty_tracking.rb +0 -1
  33. data/lib/aws/record/errors.rb +0 -8
  34. data/lib/aws/record/hash_model.rb +163 -0
  35. data/lib/aws/record/hash_model/attributes.rb +182 -0
  36. data/lib/aws/record/hash_model/finder_methods.rb +178 -0
  37. data/lib/aws/record/hash_model/scope.rb +108 -0
  38. data/lib/aws/record/model.rb +429 -0
  39. data/lib/aws/record/model/attributes.rb +377 -0
  40. data/lib/aws/record/model/finder_methods.rb +232 -0
  41. data/lib/aws/record/model/scope.rb +213 -0
  42. data/lib/aws/record/scope.rb +43 -169
  43. data/lib/aws/record/validations.rb +11 -11
  44. data/lib/aws/s3/client.rb +9 -6
  45. data/lib/aws/s3/object_collection.rb +1 -1
  46. data/lib/aws/simple_db/expect_condition_option.rb +1 -1
  47. data/lib/aws/simple_db/item_collection.rb +5 -3
  48. data/lib/aws/sts/client.rb +9 -0
  49. metadata +73 -30
  50. data/lib/aws/record/attribute.rb +0 -94
  51. data/lib/aws/record/attribute_macros.rb +0 -312
  52. data/lib/aws/record/attributes/date.rb +0 -89
  53. data/lib/aws/record/attributes/datetime.rb +0 -86
  54. data/lib/aws/record/attributes/integer.rb +0 -68
  55. data/lib/aws/record/attributes/sortable_float.rb +0 -60
  56. data/lib/aws/record/attributes/sortable_integer.rb +0 -95
  57. data/lib/aws/record/attributes/string.rb +0 -69
  58. data/lib/aws/record/base.rb +0 -828
  59. data/lib/aws/record/finder_methods.rb +0 -230
  60. data/lib/aws/record/scopes.rb +0 -55
@@ -0,0 +1,232 @@
1
+ # Copyright 2011-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"). You
4
+ # may not use this file except in compliance with the License. A copy of
5
+ # the License is located at
6
+ #
7
+ # http://aws.amazon.com/apache2.0/
8
+ #
9
+ # or in the "license" file accompanying this file. This file is
10
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11
+ # ANY KIND, either express or implied. See the License for the specific
12
+ # language governing permissions and limitations under the License.
13
+
14
+ module AWS
15
+ module Record
16
+ class Model
17
+ class << self
18
+
19
+ # @param [String] id The id of the record to load.
20
+ # @param [Hash] options
21
+ # @option options [String] :shard Specifies what shard (i.e. domain)
22
+ # should be searched.
23
+ # @raise [RecordNotFound] Raises a record not found exception if there
24
+ # was no data found for the given id.
25
+ # @return [Record::HashModel] Returns the record with the given id.
26
+ def find_by_id id, options = {}
27
+
28
+ domain = sdb_domain(options[:shard] || options[:domain])
29
+
30
+ data = domain.items[id].data.attributes
31
+
32
+ raise RecordNotFound, "no data found for id: #{id}" if data.empty?
33
+
34
+ obj = self.new(:shard => domain)
35
+ obj.send(:hydrate, id, data)
36
+ obj
37
+
38
+ end
39
+ alias_method :[], :find_by_id
40
+
41
+ # Finds records in SimpleDB and returns them as objects of the
42
+ # current class.
43
+ #
44
+ # Finding +:all+ returns an enumerable scope object
45
+ #
46
+ # People.find(:all, :order => [:age, :desc], :limit => 10).each do |person|
47
+ # puts person.name
48
+ # end
49
+ #
50
+ # Finding +:first+ returns a single record (or nil)
51
+ #
52
+ # boss = People.find(:first, :where => { :boss => true })
53
+ #
54
+ # Find accepts a hash of find modifiers (+:where+, +:order+ and
55
+ # +:limit+). You can also choose to omit these modifiers and
56
+ # chain them on the scope object returned. In the following
57
+ # example only one request is made to SimpleDB (when #each is
58
+ # called)
59
+ #
60
+ # people = People.find(:all)
61
+ #
62
+ # johns = people.where(:name => 'John Doe')
63
+ #
64
+ # johns.order(:age, :desc).limit(10).each do |suspects|
65
+ # # ...
66
+ # end
67
+ #
68
+ # See also {#where}, {#order} and {#limit} for more
69
+ # information and options.
70
+ #
71
+ # @overload find(id)
72
+ # @param id The record to find, raises an exception if the record is
73
+ # not found.
74
+ #
75
+ # @overload find(mode, options = {})
76
+ # @param [:all,:first] mode (:all) When finding +:all+ matching records
77
+ # and array is returned of records. When finding +:first+ then
78
+ # +nil+ or a single record will be returned.
79
+ # @param [Hash] options
80
+ # @option options [Mixed] :where Conditions that determine what
81
+ # records are returned.
82
+ # @option options [String,Array] :sort The order records should be
83
+ # returned in.
84
+ # @option options [Integer] :limit The max number of records to fetch.
85
+ def find *args
86
+ new_scope.find(*args)
87
+ end
88
+
89
+ # Returns a chainable scope object that restricts further scopes to a
90
+ # particular domain.
91
+ #
92
+ # Book.domain('books-2').each do |book|
93
+ # # ...
94
+ # end
95
+ #
96
+ # @param [String] domain
97
+ # @return [Scope] Returns a scope for restricting the domain of subsequent
98
+ def shard shard_name
99
+ new_scope.shard(shard_name)
100
+ end
101
+ alias_method :domain, :shard
102
+
103
+ # Returns an enumerable scope object represents all records.
104
+ #
105
+ # Book.all.each do |book|
106
+ # # ...
107
+ # end
108
+ #
109
+ # This method is equivalent to +find(:all)+, and therefore you can also
110
+ # pass aditional options. See {#find} for more information on what
111
+ # options you can pass.
112
+ #
113
+ # Book.all(:where => { :author' => 'me' }).each do |my_book|
114
+ # # ...
115
+ # end
116
+ #
117
+ # @return [Scope] Returns an enumerable scope object.
118
+ def all options = {}
119
+ new_scope.find(:all, options)
120
+ end
121
+
122
+ # Yields once for each record.
123
+ def each &block
124
+ all.each(&block)
125
+ end
126
+
127
+ # Counts records in SimpleDB.
128
+ #
129
+ # With no arguments, counts all records:
130
+ #
131
+ # People.count
132
+ #
133
+ # Accepts query options to count a subset of records:
134
+ #
135
+ # People.count(:where => { :boss => true })
136
+ #
137
+ # You can also count records on a scope object:
138
+ #
139
+ # People.find(:all).where(:boss => true).count
140
+ #
141
+ # See {#find} and {Scope#count} for more details.
142
+ #
143
+ # @param [Hash] options (<code>{}</code>) Options for counting
144
+ # records.
145
+ #
146
+ # @option options [Mixed] :where Conditions that determine what
147
+ # records are counted.
148
+ # @option options [Integer] :limit The max number of records to count.
149
+ def count(options = {})
150
+ new_scope.count(options)
151
+ end
152
+ alias_method :size, :count
153
+
154
+ # @return [Object,nil] Returns the first record found. If there were
155
+ # no records found, nil is returned.
156
+ def first options = {}
157
+ new_scope.first(options)
158
+ end
159
+
160
+ # Limits which records are retried from SimpleDB when performing a find.
161
+ #
162
+ # Simple string condition
163
+ #
164
+ # Car.where('color = "red" or color = "blue"').each {|car| ... }
165
+ #
166
+ # String with placeholders for quoting params
167
+ #
168
+ # Car.where('color = ?', 'red')
169
+ #
170
+ # Car.where('color = ? OR style = ?', 'red', 'compact')
171
+ #
172
+ # # produces a condition using in, like: WHERE color IN ('red', 'blue')
173
+ # Car.where('color IN ?', ['red','blue'])
174
+ #
175
+ # Hash arguments
176
+ #
177
+ # # WHERE age = '40' AND gender = 'male'
178
+ # People.where(:age => 40, :gender => 'male').each {|person| ... }
179
+ #
180
+ # # WHERE name IN ('John', 'Jane')
181
+ # People.where(:name => ['John', 'Jane']).each{|person| ... }
182
+ #
183
+ # Chaining where with other scope modifiers
184
+ #
185
+ # # 10 most expensive red cars
186
+ # Car.where(:color => 'red').order(:price, :desc).limit(10)
187
+ #
188
+ # @overload where(conditions_hash)
189
+ # @overload where(sql_fragment[, quote_params, ...])
190
+ #
191
+ # @param [Hash] conditions_hash A hash of attributes to values. Each
192
+ # key/value pair from the hash becomes a find condition. All conditions
193
+ # are joined by AND.
194
+ def where *args
195
+ new_scope.where(*args)
196
+ end
197
+
198
+ # Defines the order in which records are returned when performing a find.
199
+ # SimpleDB only allows sorting by one attribute per request.
200
+ #
201
+ # # oldest to youngest
202
+ # People.order(:age, :desc).each {|person| ... }
203
+ #
204
+ # You can chain order with the other scope modifiers:
205
+ #
206
+ # Pepole.order(:age, :desc).limit(10).each {|person| ... }
207
+ #
208
+ # @overload order(attribute, direction = :asc)
209
+ # @param [String,Symbol] attribute The attribute in SimpleDB to sort by.
210
+ # @param [:asc,:desc] direction (:asc) The direction to sort, ascending
211
+ # or descending order.
212
+ def order *args
213
+ new_scope.order(*args)
214
+ end
215
+
216
+ # The maximum number of records to return. By default, all records
217
+ # matching the where conditions will be returned from a find.
218
+ #
219
+ # People.limit(10).each {|person| ... }
220
+ #
221
+ # Limit can be chained with other scope modifiers:
222
+ #
223
+ # People.where(:age => 40).limit(10).each {|person| ... }
224
+ #
225
+ def limit limit
226
+ new_scope.limit(limit)
227
+ end
228
+
229
+ end
230
+ end
231
+ end
232
+ end
@@ -0,0 +1,213 @@
1
+ # Copyright 2011-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"). You
4
+ # may not use this file except in compliance with the License. A copy of
5
+ # the License is located at
6
+ #
7
+ # http://aws.amazon.com/apache2.0/
8
+ #
9
+ # or in the "license" file accompanying this file. This file is
10
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11
+ # ANY KIND, either express or implied. See the License for the specific
12
+ # language governing permissions and limitations under the License.
13
+
14
+ module AWS
15
+ module Record
16
+ class Model
17
+
18
+ # The primary interface for finding records with {AWS::Record::Model}.
19
+ #
20
+ # == Getting a Scope Object
21
+ #
22
+ # You should normally never need to construct a Scope object directly.
23
+ # Scope objects are returned from the AWS::Record::Model finder methods
24
+ # (e.g. +shard+, +where+, +order+, +limit+, etc).
25
+ #
26
+ # books = Book.where(:author => 'John Doe')
27
+ # books.class #=> AWS::Record::Scope, not Array
28
+ #
29
+ # Scopes are also returned from methods defined with the +scope+ method.
30
+ #
31
+ # == Chaining Scopes
32
+ #
33
+ # Scope objects represent a request, but do not actualy make a request
34
+ # until required. This allows you to chain requests
35
+ #
36
+ # # no request made by the following 2 statements
37
+ # books = Book.where(:author => 'John Doe')
38
+ # books = books.limit(10)
39
+ #
40
+ # books.each do |book|
41
+ # # yields up to 10 books
42
+ # end
43
+ #
44
+ # Each of the following methods returns a scope that can be chained.
45
+ #
46
+ # * {#shard}
47
+ # * {#where}
48
+ # * {#order}
49
+ # * {#limit}
50
+ #
51
+ # == Terminating Scopes
52
+ #
53
+ # To terminate a scope you can enumerate it or call #first.
54
+ #
55
+ # # terminate a scope by enumerating
56
+ # Book.limit(10).each {|book| ... }
57
+ #
58
+ # # terminate a scope by getting the first value
59
+ # Book.where('author' => 'John Doe').first
60
+ #
61
+ class Scope < Record::Scope
62
+
63
+ # @private
64
+ def initialize base_class, options = {}
65
+ super
66
+ @options[:where] ||= []
67
+ end
68
+
69
+ def new attributes = {}
70
+
71
+ attributes = attributes.dup
72
+
73
+ @options[:where].each do |conditions|
74
+ if conditions.size == 1 and conditions.first.is_a?(Hash)
75
+ attributes.merge!(conditions.first)
76
+ end
77
+ end
78
+
79
+ super(attributes)
80
+
81
+ end
82
+
83
+ # Applies conditions to the scope that limit which records are returned.
84
+ # Only those matching all given conditions will be returned.
85
+ #
86
+ # @overload where(conditions_hash)
87
+ # Specify a hash of conditions to query with. Multiple conditions
88
+ # are joined together with AND.
89
+ #
90
+ # Book.where(:author => 'John Doe', :softcover => true)
91
+ # # where `author` = `John Doe` AND `softcover` = `1`
92
+ #
93
+ # @param [Hash] conditions
94
+ #
95
+ # @overload where(conditions_string, *values)
96
+ # A sql-like query fragment with optional placeholders and values.
97
+ # Placeholders are replaced with properly quoted values.
98
+ #
99
+ # Book.where('author = ?', 'John Doe')
100
+ #
101
+ # @param [String] conditions_string A sql-like where string with
102
+ # question mark placeholders. For each placeholder there should
103
+ # be a value that will be quoted into that position.
104
+ # @param [String] *values A value that should be quoted into the
105
+ # corresponding (by position) placeholder.
106
+ #
107
+ # @return [Scope] Returns a new scope with the passed conditions applied.
108
+ def where *conditions
109
+ if conditions.empty?
110
+ raise ArgumentError, 'missing required condition'
111
+ end
112
+ _with(:where => @options[:where] + [conditions])
113
+ end
114
+
115
+ # Specifies how to sort records returned.
116
+ #
117
+ # # enumerate books, starting with the most recently published ones
118
+ # Book.order(:published_at, :desc).each do |book|
119
+ # # ...
120
+ # end
121
+ #
122
+ # Only one order may be applied. If order is specified more than
123
+ # once the last one in the chain takes precedence:
124
+ #
125
+ #
126
+ # # books returned by this scope will be ordered by :published_at
127
+ # # and not :author.
128
+ # Book.where(:read => false).order(:author).order(:published_at)
129
+ #
130
+ # @param [String,Symbol] attribute_name The attribute to sort by.
131
+ # @param [:asc, :desc] order (:asc) The direct to sort.
132
+ def order attribute_name, order = :asc
133
+ _with(:order => [attribute_name, order])
134
+ end
135
+
136
+ # @private
137
+ private
138
+ def _each_object &block
139
+
140
+ items = _item_collection
141
+
142
+ items.select.each do |item_data|
143
+ obj = base_class.new(:shard => _shard)
144
+ obj.send(:hydrate, item_data.name, item_data.attributes)
145
+ yield(obj)
146
+ end
147
+
148
+ end
149
+
150
+ # Merges another scope with this scope. Conditions are added together
151
+ # and the limit and order parts replace those in this scope (if set).
152
+ # @param [Scope] scope A scope to merge with this one.
153
+ # @return [Scope] Returns a new scope with merged conditions and
154
+ # overriden order and limit.
155
+ # @private
156
+ private
157
+ def _merge_scope scope
158
+ merged = self
159
+ scope.instance_variable_get('@options').each_pair do |opt_name,opt_value|
160
+ unless [nil, []].include?(opt_value)
161
+ if opt_name == :where
162
+ opt_value.each do |condition|
163
+ merged = merged.where(*condition)
164
+ end
165
+ else
166
+ merged = merged.send(opt_name, *opt_value)
167
+ end
168
+ end
169
+ end
170
+ merged
171
+ end
172
+
173
+ # Consumes a hash of options (e.g. +:where+, +:order+ and +:limit+) and
174
+ # builds them onto the current scope, returning a new one.
175
+ # @param [Hash] options
176
+ # @option options :where
177
+ # @option options :order
178
+ # @option options [Integer] :limit
179
+ # @return [Scope] Returns a new scope with the hash of scope
180
+ # options applied.
181
+ # @private
182
+ private
183
+ def _handle_options options
184
+ scope = self
185
+ options.each_pair do |method, args|
186
+ if method == :where and args.is_a?(Hash)
187
+ # splatting a hash turns it into an array, bad juju
188
+ scope = scope.send(method, args)
189
+ else
190
+ scope = scope.send(method, *args)
191
+ end
192
+ end
193
+ scope
194
+ end
195
+
196
+ # Converts this scope object into an AWS::SimpleDB::ItemCollection
197
+ # @return [SimpleDB::ItemCollection]
198
+ # @private
199
+ private
200
+ def _item_collection
201
+ items = base_class.sdb_domain(_shard).items
202
+ items = items.order(*@options[:order]) if @options[:order]
203
+ items = items.limit(*@options[:limit]) if @options[:limit]
204
+ @options[:where].each do |where_condition|
205
+ items = items.where(*where_condition)
206
+ end
207
+ items
208
+ end
209
+
210
+ end
211
+ end
212
+ end
213
+ end
@@ -14,90 +14,59 @@
14
14
  module AWS
15
15
  module Record
16
16
 
17
- # The primary interface for finding records with AWS::Record.
18
- #
19
- # == Getting a Scope Object
20
- #
21
- # You should normally never need to construct a Scope object directly.
22
- # Scope objects are returned from the AWS::Record::Base finder methods
23
- # (e.g. +find+ +all+, +where+, +order+, +limit+, etc).
24
- #
25
- # books = Book.where(:author => 'John Doe')
26
- # books.class #=> AWS::Record::Scope, not Array
27
- #
28
- # Scopes are also returned from methods defined with the +scope+ method.
29
- #
30
- # == Delayed Execution
31
- #
32
- # Scope objects represent a select expression, but do not actually
33
- # cause a request to be made until enumerated.
34
- #
35
- # # no request made yet
36
- # books = Book.where(:author => 'John Doe')
37
- #
38
- # # a request is made now
39
- # books.each {|book| ... }
40
- #
41
- # You can refine a scope object by calling other scope methods on
42
- # it.
43
- #
44
- # # refine the previous books Scope, no request
45
- # top_10 = books.order(:popularity, :desc).limit(10)
46
- #
47
- # # another request is made now
48
- # top_10.first
49
- #
17
+ # Base class for {AWS::Record::Model::Scope} and
18
+ # {AWS::Record::HashModel::Scope}.
50
19
  class Scope
51
20
 
52
21
  include Enumerable
53
22
 
54
- # @param [Record::Base] base_class A class that extends
55
- # {AWS::Record::Base}.
23
+ # @param base_class A class that extends {AWS::Record::AbstractBase}.
56
24
  # @param [Hash] options
57
25
  # @option options :
58
26
  # @private
59
27
  def initialize base_class, options = {}
28
+
60
29
  @base_class = base_class
30
+
61
31
  @options = options.dup
62
- @options[:where] ||= []
63
- @options[:domain] ||= base_class.domain_name
32
+
33
+ # backwards compat
34
+ @options[:shard] = @options.delete(:domain) if @options[:domain]
35
+
64
36
  end
65
37
 
66
- # @return [Class] Returns the AWS::Record::Base extending class that
38
+ # @return [Class] Returns the AWS::Record::Model extending class that
67
39
  # this scope will find records for.
68
40
  attr_reader :base_class
69
41
 
70
42
  def new attributes = {}
71
43
 
72
- options = {}
73
- options.merge!(attributes)
74
- unless options.key?(:domain) or options.key?('domain')
75
- options[:domain] = _domain
76
- end
44
+ attributes = attributes.dup
45
+ attributes[:shard] ||= attributes.delete(:shard)
46
+ attributes[:shard] ||= attributes.delete('shard')
47
+ # for backwards compatability, domain is accepted
48
+ attributes[:shard] ||= attributes.delete('domain')
49
+ attributes[:shard] ||= attributes.delete(:domain)
50
+ attributes[:shard] ||= _shard
77
51
 
78
- @options[:where].each do |conditions|
79
- if conditions.size == 1 and conditions.first.is_a?(Hash)
80
- options.merge!(conditions.first)
81
- end
82
- end
83
-
84
- base_class.new(options)
52
+ base_class.new(attributes)
85
53
 
86
54
  end
87
55
  alias_method :build, :new
88
56
 
89
- # @param [String] domain
90
- # @return [Scope] Returns a scope for restricting the domain of subsequent
91
- # scope operations
92
- def domain name
93
- _with(:domain => name)
57
+ # @param [String] shard_name
58
+ # @return [Scope] Returns a scope that specifies which shard
59
+ # (i.e. SimpleDB domain) should be used.
60
+ def shard shard_name
61
+ _with(:shard => shard_name)
94
62
  end
63
+ alias_method :domain, :shard
95
64
 
96
65
  # @overload find(id)
97
66
  # Finds and returns a single record by id. If no record is found
98
67
  # with the given +id+, then a RecordNotFound error will be raised.
99
68
  # @param [String] id ID of the record to find.
100
- # @return [Record::Base] Returns the record.
69
+ # @return Returns the record.
101
70
  #
102
71
  # @overload find(:first, options = {})
103
72
  # Returns the first record found. If no records were matched then
@@ -125,7 +94,7 @@ module AWS
125
94
  when id_or_mode == :all then scope
126
95
  when id_or_mode == :first then scope.limit(1).to_a.first
127
96
  else
128
- base_class.find_by_id(id_or_mode, :domain => scope._domain)
97
+ base_class.find_by_id(id_or_mode, :shard => scope._shard)
129
98
  end
130
99
 
131
100
  end
@@ -141,64 +110,11 @@ module AWS
141
110
  end
142
111
  alias_method :size, :count
143
112
 
144
- # @return [Record::Base,nil] Gets the first record from the domain
145
- # and returns it, or returns nil if the domain is empty.
113
+ # @return Returns the first record found, returns
114
+ # nil if the domain/table is empty.
146
115
  def first options = {}
147
116
  _handle_options(options).find(:first)
148
117
  end
149
-
150
- # Applies conditions to the scope that limit which records are returned.
151
- # Only those matching all given conditions will be returned.
152
- #
153
- # @overload where(conditions_hash)
154
- # Specify a hash of conditions to query with. Multiple conditions
155
- # are joined together with AND.
156
- #
157
- # Book.where(:author => 'John Doe', :softcover => true)
158
- # # where `author` = `John Doe` AND `softcover` = `1`
159
- #
160
- # @param [Hash] conditions
161
- #
162
- # @overload where(conditions_string, *values)
163
- # A sql-like query fragment with optional placeholders and values.
164
- # Placeholders are replaced with properly quoted values.
165
- #
166
- # Book.where('author = ?', 'John Doe')
167
- #
168
- # @param [String] conditions_string A sql-like where string with
169
- # question mark placeholders. For each placeholder there should
170
- # be a value that will be quoted into that position.
171
- # @param [String] *values A value that should be quoted into the
172
- # corresponding (by position) placeholder.
173
- #
174
- # @return [Scope] Returns a new scope with the passed conditions applied.
175
- def where *conditions
176
- if conditions.empty?
177
- raise ArgumentError, 'missing required condition'
178
- end
179
- _with(:where => @options[:where] + [conditions])
180
- end
181
-
182
- # Specifies how to sort records returned.
183
- #
184
- # # enumerate books, starting with the most recently published ones
185
- # Book.order(:published_at, :desc).each do |book|
186
- # # ...
187
- # end
188
- #
189
- # Only one order may be applied. If order is specified more than
190
- # once the last one in the chain takes precedence:
191
- #
192
- #
193
- # # books returned by this scope will be ordered by :published_at
194
- # # and not :author.
195
- # Book.where(:read => false).order(:author).order(:published_at)
196
- #
197
- # @param [String,Symbol] attribute_name The attribute to sort by.
198
- # @param [:asc, :desc] order (:asc) The direct to sort.
199
- def order attribute_name, order = :asc
200
- _with(:order => [attribute_name, order])
201
- end
202
118
 
203
119
  # Limits the maximum number of total records to return when finding
204
120
  # or counting. Returns a scope, does not make a request.
@@ -229,28 +145,21 @@ module AWS
229
145
  end
230
146
 
231
147
  protected
232
- def _domain
233
- @options[:domain]
148
+ def _shard
149
+ @options[:shard] || base_class.shard_name
234
150
  end
151
+ alias_method :domain, :shard
235
152
 
236
153
  # @private
237
154
  private
238
155
  def _each_object &block
239
-
240
- items = _item_collection
241
-
242
- items.select.each do |item_data|
243
- obj = base_class.new(:domain => _domain)
244
- obj.send(:hydrate, item_data.name, item_data.attributes)
245
- yield(obj)
246
- end
247
-
156
+ raise NotImplementedError
248
157
  end
249
158
 
250
159
  # @private
251
160
  private
252
161
  def _with options
253
- Scope.new(base_class, @options.merge(options))
162
+ self.class.new(base_class, @options.merge(options))
254
163
  end
255
164
 
256
165
  # @private
@@ -260,66 +169,31 @@ module AWS
260
169
  _merge_scope(base_class.send(scope_name, *args))
261
170
  end
262
171
 
263
- # Merges another scope with this scope. Conditions are added together
264
- # and the limit and order parts replace those in this scope (if set).
265
- # @param [Scope] scope A scope to merge with this one.
266
- # @return [Scope] Returns a new scope with merged conditions and
267
- # overriden order and limit.
172
+ # Merges the one scope with the current scope, returning a 3rd.
173
+ # @param [Scope] scope
174
+ # @return [Scope]
268
175
  # @private
269
176
  private
270
177
  def _merge_scope scope
271
- merged = self
272
- scope.instance_variable_get('@options').each_pair do |opt_name,opt_value|
273
- unless [nil, []].include?(opt_value)
274
- if opt_name == :where
275
- opt_value.each do |condition|
276
- merged = merged.where(*condition)
277
- end
278
- else
279
- merged = merged.send(opt_name, *opt_value)
280
- end
281
- end
282
- end
283
- merged
178
+ raise NotImplementedError
284
179
  end
285
180
 
286
- # Consumes a hash of options (e.g. +:where+, +:order+ and +:limit+) and
287
- # builds them onto the current scope, returning a new one.
288
- # @param [Hash] options
289
- # @option options :where
290
- # @option options :order
291
- # @option options [Integer] :limit
292
- # @return [Scope] Returns a new scope with the hash of scope
293
- # options applied.
181
+ # Consumes a hash of options (e.g. +:shard+, +:limit) and returns
182
+ # a new scope with those applied.
183
+ # @return [Scope]
294
184
  # @private
295
185
  private
296
186
  def _handle_options options
297
- scope = self
298
- options.each_pair do |method, args|
299
- if method == :where and args.is_a?(Hash)
300
- # splatting a hash turns it into an array, bad juju
301
- scope = scope.send(method, args)
302
- else
303
- scope = scope.send(method, *args)
304
- end
305
- end
306
- scope
187
+ raise NotImplementedError
307
188
  end
308
189
 
309
- # Converts this scope object into an AWS::SimpleDB::ItemCollection
310
- # @return [SimpleDB::ItemCollection]
311
190
  # @private
312
191
  private
313
192
  def _item_collection
314
- items = base_class.sdb_domain(_domain).items
315
- items = items.order(*@options[:order]) if @options[:order]
316
- items = items.limit(*@options[:limit]) if @options[:limit]
317
- @options[:where].each do |where_condition|
318
- items = items.where(*where_condition)
319
- end
320
- items
193
+ raise NotImplementedError
321
194
  end
322
195
 
323
196
  end
197
+
324
198
  end
325
199
  end