amazon_sdb 0.6.0 → 0.6.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,9 @@
1
+ == 0.6.5 / 2008-01-15
2
+ * 3 major enhancements
3
+ * New usage tracking via the box_usage method
4
+ * Better docs
5
+ * Boolean coercion
6
+
1
7
  == 0.6.0 / 2007-12-28
2
8
  * 2 major enhancements
3
9
  * Correct error handling for API's HTTP responses (with tests)
data/README.txt CHANGED
@@ -9,11 +9,11 @@ http://code.nytimes.com/svn/ruby/gems/amazon_sdb
9
9
 
10
10
  == DESCRIPTION:
11
11
 
12
- Amazon sdb is a Ruby wrapper to Amazon's new Simple Database Service. Amazon sdb is a different type of database:
12
+ Amazon SDB is a Ruby wrapper to Amazon's new Simple Database Service. Amazon sdb is a different type of database:
13
13
 
14
14
  * Accessed over the network via RESTful calls
15
15
  * No schemas or types
16
- * Each sdb account can have up to 100 domains for data.
16
+ * Each SimpleDB account can have up to 100 domains for data.
17
17
  * Domains can hold objects referenced by unique keys
18
18
  * Each object can hold up to 256 name/value attributes.
19
19
  * Only name/value pairs must be unique in an objects attributes, there can be multiple name/value attributes with the same name.
@@ -22,9 +22,9 @@ Amazon sdb is a Ruby wrapper to Amazon's new Simple Database Service. Amazon sdb
22
22
 
23
23
  == FEATURES:
24
24
 
25
- * A basic interface to Amazon sdb
26
- * Includes a class for representing attribute sets in sdb
27
- * Automatic conversion to/from sdb representations for integers and dates (for floats, it's suggested you use the Multimap#numeric function)
25
+ * A basic interface to Amazon SimpleDB
26
+ * Includes a class for representing attribute sets in SimpleDB
27
+ * Automatic conversion to/from SimpleDB representations for integers and dates (for floats, it's suggested you use the Multimap#numeric function)
28
28
  * The beginnings of mock-based tests for methods derived from Amazon's docs
29
29
 
30
30
  == CAVEATS
@@ -41,7 +41,7 @@ Amazon sdb is a Ruby wrapper to Amazon's new Simple Database Service. Amazon sdb
41
41
 
42
42
  == SYNOPSIS:
43
43
 
44
- b = Amazon::sdb::Base.new(aws_public_key, aws_secret_key)
44
+ b = Amazon::SDB::Base.new(aws_public_key, aws_secret_key)
45
45
  b.domains #=> list of domain
46
46
  domain = b.create_domain 'my domain'
47
47
 
@@ -30,10 +30,11 @@ require 'amazon_sdb/domain'
30
30
  require 'amazon_sdb/item'
31
31
  require 'amazon_sdb/resultset'
32
32
  require 'amazon_sdb/exceptions'
33
+ require 'amazon_sdb/usage'
33
34
 
34
35
  module Amazon
35
36
  module SDB
36
- VERSION = '0.6.0'
37
+ VERSION = '0.6.5'
37
38
  end
38
39
  end
39
40
 
@@ -15,6 +15,8 @@ module Amazon
15
15
  def initialize(aws_access_key, aws_secret_key)
16
16
  @access_key = aws_access_key
17
17
  @secret_key = aws_secret_key
18
+ @usage = Usage.new
19
+ raise @usage
18
20
  end
19
21
 
20
22
  ##
@@ -32,16 +34,42 @@ module Amazon
32
34
  @@number_padding = num
33
35
  end
34
36
 
37
+ ##
38
+ # The number of digits after the decimal points to use by default
35
39
  def self.float_precision
36
40
  return @@float_precision
37
41
  end
38
42
 
43
+ ##
44
+ # Set the #float_precision
39
45
  def self.float_precision=(num)
40
46
  return @@float_precision
41
47
  end
42
48
 
43
49
  ##
44
- # Retrieves a list of domains in your SDS database. Each entry is a Domain object.
50
+ # Returns the Box Usage accumulated since the beginning of the session. Box Usage represents computation time and is one of
51
+ # the parameters in your monthly SimpleDB bill. As an alternative, when passed a block (no parameters yielded), it returns
52
+ # the box usage only for the operations within the block.
53
+ def box_usage
54
+ unless block_given?
55
+ @usage.box_usage
56
+ else
57
+ # return the usage of the actions in the block
58
+ usage1 = @usage.box_usage
59
+ yield
60
+ usage2 = @usage.box_usage
61
+ return usage2 - usage1
62
+ end
63
+ end
64
+
65
+ ##
66
+ # Resets the box usage accumulated within the current session. Not sure why you'd need to do this, but it's provided.
67
+ def reset_usage!
68
+ @usage.reset!
69
+ end
70
+
71
+ ##
72
+ # Retrieves a list of domains in your SDS database. Each entry is a Domain object.
45
73
  def domains
46
74
  domains = []
47
75
  nextToken = nil
@@ -67,10 +95,35 @@ module Amazon
67
95
  end
68
96
 
69
97
  ##
70
- # Returns a domain object for SDS. Assumes the domain already exists, so errors might occur if you didn't create it.
98
+ # Returns a domain object for SimpleDB. Assumes the domain already exists, so a ParameterError (NoSuchDomain) might occur if it's not there. This
99
+ # method is useful for getting a domain object without having to incur the operational costs of querying all domains.
71
100
  def domain(name)
72
101
  Domain.new(@access_key, @secret_key, name)
73
102
  end
103
+
104
+ ##
105
+ # Creates a domain. This operation is idempotent, but it is slow and if you are sure the domain already exists, you might
106
+ # want to use the #domain method instead. Each SimpleDB account is allowed up to 100 domains; a LimitError will be raised
107
+ # if you attempt to create more.
108
+ def create_domain(name)
109
+ sdb_query({:Action => 'CreateDomain', 'DomainName' => name}) do |h|
110
+ domain(name)
111
+ end
112
+ end
113
+
114
+ ##
115
+ # Deletes a domain. Running this command multiple times or on a domain that does not exist will NOT return an error.
116
+ def delete_domain!(name)
117
+ sdb_query({:Action => 'DeleteDomain', 'DomainName' => name})
118
+ end
119
+
120
+ private
121
+ def parse_usage(hpricot)
122
+ usagenode = hpricot.at('//BoxUsage')
123
+ return unless usagenode
124
+
125
+ @usage.add_usage usagenode.innerText.to_f
126
+ end
74
127
 
75
128
  def raise_errors(hpricot)
76
129
  errnode = hpricot.at('//Errors/Error')
@@ -102,18 +155,6 @@ module Amazon
102
155
  end
103
156
  end
104
157
 
105
- def create_domain(name)
106
- sdb_query({:Action => 'CreateDomain', 'DomainName' => name}) do |h|
107
- domain(name)
108
- end
109
- end
110
-
111
- ##
112
- # Deletes a domain. This operation is currently not supported by SDS.
113
- def delete_domain!(name)
114
- sdb_query({:Action => 'DeleteDomain', 'DomainName' => name})
115
- end
116
-
117
158
  def timestamp
118
159
  Time.now.iso8601
119
160
  end
@@ -148,11 +189,13 @@ module Amazon
148
189
  open(url) do |f|
149
190
  h = Hpricot.XML(f)
150
191
 
192
+ parse_usage h
151
193
  raise_errors h
152
194
  yield h if block_given?
153
195
  end
154
196
  rescue OpenURI::HTTPError => e
155
197
  h = Hpricot.XML(e.io.read)
198
+ parse_usage h
156
199
  raise_errors h
157
200
  end
158
201
  end
@@ -166,7 +209,6 @@ module Amazon
166
209
  return hmac(key, option_array.map {|pair| pair[0]+pair[1]}.join('')).chop
167
210
  end
168
211
 
169
- private
170
212
  @@number_padding = 32
171
213
  @@float_precision = 8
172
214
 
@@ -22,9 +22,9 @@ module Amazon
22
22
  ##
23
23
  # Sets attributes for a given key in the domain. If there are no attributes supplied, it creates an empty set.
24
24
  # Takes the following arguments:
25
- # - key - a string key for the attribute set
26
- # - multimap - an collection of attributes for the set in a Multimap object. If nothing, creates an empty set.
27
- # - options - for put options
25
+ # - <tt>key</tt> - a string key for the attribute set
26
+ # - <tt>multimap</tt> - an collection of attributes for the set in a Multimap object (can convert a Hash and Array too). If nothing, creates an empty set.
27
+ # - <tt>options</tt> - for put options. Currently the only option is :replace, which either takes an array of attribute names to replace or :all for all of them
28
28
  def put_attributes(key, multimap=nil, options = {})
29
29
  req_options = {'Action' => 'PutAttributes', 'DomainName' => name, 'ItemName' => key}
30
30
 
@@ -52,6 +52,7 @@ module Amazon
52
52
  ##
53
53
  # Gets the attribute list for a key. Arguments:
54
54
  # - <tt>key</tt> - the key for the attribute set
55
+ # - <tt>attr_list</tt> - by default, this function returns all the attributes of an item. If you wanted to limit the response to only a few named attributes, you can pass them here.
55
56
  def get_attributes(key, *attr_list)
56
57
  options = {'Action' => 'GetAttributes', 'DomainName' => name, 'ItemName' => key}
57
58
 
@@ -75,7 +76,9 @@ module Amazon
75
76
  end
76
77
 
77
78
  ##
78
- # Not implemented yet.
79
+ # Deletes the attributes associated with a particular item. If the optional <tt>multimap</tt> argument is nil, deletes the entire
80
+ # object. Otherwise, the optional multimap argument can be used to delete specific key/value pairs in the object (also accepts
81
+ # a String or Symbol for a single name, an Array for multiple keys or a Hash for key/value pairs)
79
82
  def delete_attributes(key, multimap=nil)
80
83
  options = {'Action' => 'DeleteAttributes', 'DomainName' => name, 'ItemName' => key}
81
84
 
@@ -106,9 +109,10 @@ module Amazon
106
109
  ##
107
110
  # Returns a list of matching items that match a filter
108
111
  # Options include:
109
- # - <tt>max_results</tt> = the max items to return for a listing (top/default is 100)
110
- # - <tt>:more_token</tt> = to retrieve a second or more page of results, the more token should be provided
111
- # - <tt>:load_attrs</tt> = this query normally returns just a list of names, the attributes have to be retrieved separately. To load the attributes for matching results automatically, set to true (normally false)
112
+ # - <tt>:expr</tt> - a query expression to evaluate (see the Amazon SimpleDB documentation for details)
113
+ # - <tt>:max_results</tt> - the max items to return for a listing (top/default is 100)
114
+ # - <tt>:next_token</tt> - to retrieve a second or more page of results, the more token should be provided
115
+ # - <tt>:load_attrs</tt> - this query normally returns just a list of names, the attributes have to be retrieved separately. To load the attributes for matching results automatically, set to true (normally false). Be aware this will lead to N additional requests to SimpleDB.
112
116
  def query(query_options = {})
113
117
  req_options = {'Action' => 'Query', 'DomainName' => name}
114
118
 
@@ -4,46 +4,80 @@ module Amazon
4
4
  end
5
5
 
6
6
  ACCESS_ERROR_CODES = %w{AccessFailure}
7
+
8
+ ##
9
+ # The AccessError represents access problems connecting to SimpleDB
7
10
  class AccessError < Error
8
11
  end
9
12
 
10
13
  AUTH_ERROR_CODES = %w{AuthFailure AuthMissingFailure InvalidHTTPAuthHeader OptInRequired}
14
+
15
+ ##
16
+ # AuthError represents several different authentication problems that may occur when connecting to Amazon SimpleDB. See the
17
+ # message for details.
11
18
  class AuthError < Error
12
19
  end
13
20
 
14
21
  PARAMETER_ERROR_CODES = %w(InvalidAction InvalidNextToken InvalidParameterError
15
22
  InvalidParameterCombination InvalidParameterValue MissingAction MissingParameter NoSuchDomain
16
23
  )
24
+
25
+ ##
26
+ # ParameterError is returned when a parameter to SimpleDB is invalid or missing. See the error for details.
17
27
  class ParameterError < Error
18
28
  end
19
29
 
20
30
  QUERY_ERROR_CODES = %w{InvalidNumberPredicates InvalidNumberValueTests InvalidQueryExpression}
31
+
32
+ ##
33
+ # The QuerySyntaxError covers several errors that may result from an invalid <tt>:expr</tt> passed into the Domain#Query method.
21
34
  class QuerySyntaxError < Error
22
35
  end
23
36
 
24
37
  LIMIT_ERROR_CODES = %w{NumberDomainsExceeded NumberDomainAttributesExceeded NumberDomainBytesExceeded NumberDomainBytesExceeeded URITooLong}
38
+
39
+ ##
40
+ # A LimitError is returned when you hit one of the fundamental limits for SimpleDB accounts. See the message content for details.
25
41
  class LimitError < Error
26
42
  end
27
43
 
28
44
  SERVER_ERROR_CODES = %w{InternalError ServiceOverload ServiceUnavailable}
45
+
46
+ ##
47
+ # ServerErrors represent server problems on SimpleDB.
29
48
  class ServerError < Error
30
49
  end
31
50
 
51
+ ##
52
+ # Huh? What? For when SimpleDB sends me an error code I've never seen before (and isn't in the docs)
32
53
  class UnknownError < Error
33
54
  end
34
55
 
35
56
  REQUEST_ERROR_CODES = %w{InvalidHttpRequest InvalidSOAPRequest InvalidURI InvalidService UnsupportedHttpVerb}
57
+
58
+ ##
59
+ # For incorrectly constructed HTTP queries against the SimpleDB server. If you see this error, it's my fault, and let me know
60
+ # the command that caused it.
36
61
  class RequestError < Error
37
62
  end
38
63
 
39
64
  TIMEOUT_ERROR_CODES = %w{RequestExpired RequestTimeout RequestThrottled}
65
+
66
+ ##
67
+ # Amazon SimpleDB times out any operation that lasts more than 5 seconds. This error will be returned.
40
68
  class TimeoutError < Error
41
69
  end
42
70
 
43
71
  VERSION_ERROR_CODES = %w{FeatureDeprecated NoSuchVersion NotYetImplemented}
72
+
73
+ ##
74
+ # For when there is a mismatch between this gem and the API being called.
44
75
  class VersionError < Error
45
76
  end
46
77
 
78
+ ##
79
+ # When GetAttributes doesn't match, Amazon returns an empty record. I prefer to raise an exception instead, so there will be no
80
+ # confusion.
47
81
  class RecordNotFoundError < Error
48
82
  end
49
83
  end
@@ -1,7 +1,7 @@
1
1
  module Amazon
2
2
  module SDB
3
3
  ##
4
- # An item from sdb. This basically is a key for the item in the domain and a Multimap of the attributes. You should never
4
+ # An item from SimpleDB. This basically is a key for the item in the domain and a Multimap of the attributes. You should never
5
5
  # call Item#new, instead it is returned by various methods in Domain and ResultSet
6
6
  class Item
7
7
  include Enumerable
@@ -13,23 +13,34 @@ module Amazon
13
13
  @attributes = multimap
14
14
  end
15
15
 
16
+ ##
17
+ # Reloads from the domain
16
18
  def reload!
17
19
  item = @domain.get_attributes(@key)
18
20
  @attributes = item.attributes
19
21
  end
20
22
 
23
+ ##
24
+ # Returns true if the attributes are empty
21
25
  def empty?
26
+ return true if @attributes.nil?
22
27
  @attributes.size == 0
23
28
  end
24
29
 
30
+ ##
31
+ # Deletes the item in SimpleDB
25
32
  def destroy!
26
33
  @domain.delete_attributes(@key)
27
34
  end
28
35
 
36
+ ##
37
+ # Saves the item back (like a put_attributes with :replace => :all
29
38
  def save
30
- @domain.put_attributes(@key, @attributes)
39
+ @domain.put_attributes(@key, @attributes, :replace => :all)
31
40
  end
32
41
 
42
+ ##
43
+ # Reloads the item if necessary
33
44
  def get(key)
34
45
  reload! if @attributes.nil?
35
46
  @attributes.get(key)
@@ -172,6 +172,10 @@ module Amazon
172
172
 
173
173
  def sdb_value_escape(value)
174
174
  case value
175
+ when TrueClass
176
+ "true"
177
+ when FalseClass
178
+ "false"
175
179
  when Fixnum
176
180
  sprintf("%0#{Base.number_padding}d", value)
177
181
  when Float
@@ -204,6 +208,10 @@ module Amazon
204
208
 
205
209
  def coerce(value)
206
210
  case value
211
+ when 'true'
212
+ true
213
+ when 'false'
214
+ false
207
215
  when /^0+\d+$/
208
216
  value.to_i
209
217
  when /^0+\d*.\d+$/
@@ -0,0 +1,56 @@
1
+ require "test_sdb_harness"
2
+
3
+ class TestItem < Test::Unit::TestCase
4
+ def setup
5
+ @domain = Amazon::SDB::Domain.new 'API_KEY', 'SECRET_KEY', 'testdb'
6
+ @key = 'TEST_ITEM'
7
+ @multimap = Amazon::SDB::Multimap.new({"foo" => "bar", "baz" => "quux"})
8
+
9
+ @empty_item = Amazon::SDB::Item.new(@domain, @key)
10
+ @item = Amazon::SDB::Item.new(@domain, @key, @multimap)
11
+ end
12
+
13
+ def test_save
14
+ @domain.responses << generic_response('PutAttributes')
15
+ @item.save
16
+
17
+ assert_in_url_query({'Action' => 'PutAttributes', 'DomainName' => 'testdb', 'ItemName' => 'TEST_ITEM',
18
+ 'Attribute.0.Replace' => 'true', 'Attribute.1.Replace' => 'true'}, @domain.uris.first)
19
+ end
20
+
21
+ def test_reload!
22
+ # tests sends a get attributes
23
+ @domain.responses << <<-EOF
24
+ <GetAttributesResponse xmlns="http://sdb.amazonaws.com/doc/2007-11-07">
25
+ <GetAttributesResult>
26
+ <Attribute><Name>Color</Name><Value>Blue</Value></Attribute>
27
+ <Attribute><Name>Size</Name><Value>Med</Value></Attribute>
28
+ <Attribute><Name>Price</Name><Value>14</Value></Attribute>
29
+ </GetAttributesResult>
30
+ <ResponseMetadata>
31
+ <RequestId>b1e8f1f7-42e9-494c-ad09-2674e557526d</RequestId>
32
+ <BoxUsage>0.0000219907/<BoxUsage>
33
+ </ResponseMetadata>
34
+ </GetAttributesResponse>
35
+ EOF
36
+
37
+ @item.reload!
38
+
39
+ assert_in_url_query({'Action' => 'GetAttributes', 'DomainName' => 'testdb', 'ItemName' => 'TEST_ITEM'}, @domain.uris.first)
40
+ end
41
+
42
+ def test_empty?
43
+ assert @empty_item.empty?
44
+ assert !@item.empty?
45
+ end
46
+
47
+ def test_destroy!
48
+ # tests sends a delete attributes with 0 attrs
49
+ @domain.responses << generic_response('DeleteAttributes')
50
+
51
+ @item.destroy!
52
+ assert_in_url_query({'Action' => 'DeleteAttributes', 'DomainName' => 'testdb', 'ItemName' => 'TEST_ITEM'}, @domain.uris.first)
53
+ end
54
+ end
55
+
56
+
@@ -105,6 +105,12 @@ class TestMultimap < Test::Unit::TestCase
105
105
  @m['Num'] = Amazon::SDB::Multimap.numeric(12.34, 10, 4)
106
106
  assert_equal '00012.3400', @m['Num']
107
107
  end
108
+
109
+ def test_boolean_to_sdb
110
+ @m['a'] = true
111
+
112
+ assert_equal 'true', @m.to_sdb['Attribute.0.Value']
113
+ end
108
114
 
109
115
  def test_to_sdb_replace_all
110
116
  @m[:a] = "foo"
@@ -166,6 +172,14 @@ class TestMultimap < Test::Unit::TestCase
166
172
  assert_equal "0000000000034.3400000000", m.get("a", :before_cast => true)
167
173
  end
168
174
 
175
+ def test_coerce_boolean
176
+ m = Multimap.new
177
+ m.from_sdb([["a", "true"], ["b", "false"]])
178
+
179
+ assert_equal true, m["a"]
180
+ assert_equal false, m["b"]
181
+ end
182
+
169
183
  def test_coerce_datetime
170
184
  now = Time.now
171
185
 
@@ -9,6 +9,7 @@ class Amazon::SDB::Base
9
9
  def initialize(aws_access_key, aws_secret_key)
10
10
  @access_key = aws_access_key
11
11
  @secret_key = aws_secret_key
12
+ @usage = Amazon::SDB::Usage.new
12
13
  @responses = []
13
14
  @uris = []
14
15
  end
@@ -0,0 +1,113 @@
1
+ require "test_sdb_harness"
2
+
3
+ class TestUsage < Test::Unit::TestCase
4
+ include Amazon::SDB
5
+
6
+ def setup
7
+ @sdb = Amazon::SDB::Base.new 'API_KEY', 'SECRET_KEY'
8
+ end
9
+
10
+ def test_accumulate
11
+ u = Amazon::SDB::Usage.new
12
+
13
+ u << 0.50
14
+ u << 0.25
15
+
16
+ assert_in_delta(0.75, u.box_usage, 2 ** -20)
17
+ end
18
+
19
+ def test_reset
20
+ u = Amazon::SDB::Usage.new
21
+
22
+ u << 0.50
23
+ u << 0.25
24
+
25
+ u.reset!
26
+
27
+ assert_in_delta(0.0, u.box_usage, 2 ** -20)
28
+ end
29
+
30
+ def test_request_usage
31
+ @sdb.responses << <<-EOF
32
+ <?xml version="1.0" encoding="utf-8" ?>
33
+ <ListDomainsResponse xmlns="http://sdb.amazonaws.com/doc/2007-11-07">
34
+ <ListDomainsResult>
35
+ <DomainName>foo</DomainName>
36
+ <DomainName>bar</DomainName>
37
+ <DomainName>baz</DomainName>
38
+ </ListDomainsResult>
39
+ <ResponseMetadata>
40
+ <RequestId>eb13162f-1b95-4511-8b12-489b86acfd28</RequestId>
41
+ <BoxUsage>0.00777</BoxUsage>
42
+ </ResponseMetadata>
43
+ </ListDomainsResponse>
44
+ EOF
45
+
46
+ @sdb.domains
47
+
48
+ assert_in_delta(0.00777, @sdb.box_usage, 2 ** -20)
49
+ end
50
+
51
+ def test_error_usage
52
+ @sdb.responses << error_response('RequestTimeout')
53
+
54
+ assert_raise(Amazon::SDB::TimeoutError) { @sdb.domains }
55
+ assert_in_delta(0.0000219907, @sdb.box_usage, 2 ** -20)
56
+ end
57
+
58
+ def test_block_usage
59
+ @sdb.responses << <<-EOF
60
+ <?xml version="1.0" encoding="utf-8" ?>
61
+ <ListDomainsResponse xmlns="http://sdb.amazonaws.com/doc/2007-11-07">
62
+ <ListDomainsResult>
63
+ <DomainName>foo</DomainName>
64
+ <DomainName>bar</DomainName>
65
+ <DomainName>baz</DomainName>
66
+ </ListDomainsResult>
67
+ <ResponseMetadata>
68
+ <RequestId>eb13162f-1b95-4511-8b12-489b86acfd28</RequestId>
69
+ <BoxUsage>0.50</BoxUsage>
70
+ </ResponseMetadata>
71
+ </ListDomainsResponse>
72
+ EOF
73
+
74
+ @sdb.responses << <<-EOF
75
+ <?xml version="1.0" encoding="utf-8" ?>
76
+ <ListDomainsResponse xmlns="http://sdb.amazonaws.com/doc/2007-11-07">
77
+ <ListDomainsResult>
78
+ <DomainName>foo</DomainName>
79
+ <DomainName>bar</DomainName>
80
+ <DomainName>baz</DomainName>
81
+ </ListDomainsResult>
82
+ <ResponseMetadata>
83
+ <RequestId>eb13162f-1b95-4511-8b12-489b86acfd28</RequestId>
84
+ <BoxUsage>0.25</BoxUsage>
85
+ </ResponseMetadata>
86
+ </ListDomainsResponse>
87
+ EOF
88
+
89
+ @sdb.responses << <<-EOF
90
+ <?xml version="1.0" encoding="utf-8" ?>
91
+ <ListDomainsResponse xmlns="http://sdb.amazonaws.com/doc/2007-11-07">
92
+ <ListDomainsResult>
93
+ <DomainName>foo</DomainName>
94
+ <DomainName>bar</DomainName>
95
+ <DomainName>baz</DomainName>
96
+ </ListDomainsResult>
97
+ <ResponseMetadata>
98
+ <RequestId>eb13162f-1b95-4511-8b12-489b86acfd28</RequestId>
99
+ <BoxUsage>0.01</BoxUsage>
100
+ </ResponseMetadata>
101
+ </ListDomainsResponse>
102
+ EOF
103
+
104
+ @sdb.domains
105
+
106
+ usage = @sdb.box_usage do
107
+ @sdb.domains
108
+ @sdb.domains
109
+ end
110
+
111
+ assert_in_delta(0.26, usage, 2 ** -20)
112
+ end
113
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: amazon_sdb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.6.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jacob Harris
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2007-12-28 00:00:00 -05:00
12
+ date: 2008-01-14 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -79,7 +79,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
79
79
  requirements: []
80
80
 
81
81
  rubyforge_project: nytimes
82
- rubygems_version: 1.0.0
82
+ rubygems_version: 1.0.1
83
83
  signing_key:
84
84
  specification_version: 2
85
85
  summary: A ruby wrapper to Amazon's sdb service
@@ -87,5 +87,7 @@ test_files:
87
87
  - test/test_amazon_base.rb
88
88
  - test/test_amazon_domain.rb
89
89
  - test/test_exceptions.rb
90
+ - test/test_item.rb
90
91
  - test/test_multimap.rb
91
92
  - test/test_sdb_harness.rb
93
+ - test/test_usage.rb