simplydb 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +5 -21
- data/Gemfile +4 -0
- data/README.md +37 -0
- data/Rakefile +10 -50
- data/lib/simplydb.rb +2 -3
- data/lib/simplydb/client.rb +71 -58
- data/lib/simplydb/error.rb +62 -57
- data/lib/simplydb/interface.rb +36 -54
- data/lib/simplydb/server.rb +74 -0
- data/lib/simplydb/version.rb +3 -0
- data/simplydb.gemspec +25 -77
- data/spec/client_spec.rb +17 -5
- data/spec/error_spec.rb +15 -5
- data/spec/fixtures/vcr/create_env.yml +313 -0
- data/spec/fixtures/vcr/delete_domains.yml +119 -0
- data/spec/fixtures/vcr/delete_items.yml +81 -0
- data/spec/fixtures/vcr/delete_items_all.yml +79 -0
- data/spec/fixtures/vcr/destroy_env.yml +197 -0
- data/spec/fixtures/vcr/get_all_items.yml +43 -0
- data/spec/fixtures/vcr/get_domains.yml +41 -0
- data/spec/fixtures/vcr/get_items.yml +42 -0
- data/spec/fixtures/vcr/put_domains.yml +119 -0
- data/spec/fixtures/vcr/put_items.yml +81 -0
- data/spec/fixtures/vcr/show_domains.yml +42 -0
- data/spec/interface_spec.rb +75 -92
- data/spec/server_spec.rb +236 -0
- data/spec/spec_helper.rb +19 -11
- data/spec/support/vcr.rb +7 -0
- metadata +131 -56
- data/.document +0 -5
- data/LICENSE +0 -20
- data/README.rdoc +0 -37
- data/VERSION +0 -1
- data/examples/interface.rb +0 -19
- data/examples/record.rb +0 -45
- data/lib/simplydb/clients/typhoeus.rb +0 -35
- data/lib/simplydb/extensions.rb +0 -21
- data/lib/simplydb/record.rb +0 -2
- data/lib/simplydb/record/base.rb +0 -282
- data/spec/extensions_spec.rb +0 -15
- data/spec/record/base_spec.rb +0 -214
- data/spec/spec.opts +0 -2
data/.gitignore
CHANGED
@@ -1,21 +1,5 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
tmtags
|
7
|
-
|
8
|
-
## EMACS
|
9
|
-
*~
|
10
|
-
\#*
|
11
|
-
.\#*
|
12
|
-
|
13
|
-
## VIM
|
14
|
-
*.swp
|
15
|
-
|
16
|
-
## PROJECT::GENERAL
|
17
|
-
coverage
|
18
|
-
rdoc
|
19
|
-
pkg
|
20
|
-
|
21
|
-
## PROJECT::SPECIFIC
|
1
|
+
pkg/*
|
2
|
+
*.gem
|
3
|
+
.bundle
|
4
|
+
Gemfile.lock
|
5
|
+
.idea/*
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# simplydb
|
2
|
+
|
3
|
+
A minimal interface to Amazon SimpleDB that has separation of interfaces. Build to support a Sinatra app that can be used as a JSON <-> SimpleDB proxy.
|
4
|
+
|
5
|
+
require 'rubygems'
|
6
|
+
require 'simplydb'
|
7
|
+
|
8
|
+
interface = SimplyDB::Interface.new({
|
9
|
+
:access_key => ENV['AWS_ACCESS_KEY'],
|
10
|
+
:secret_key => ENV['AWS_SECRET_KEY']
|
11
|
+
})
|
12
|
+
|
13
|
+
if interface.create_domain("MyDomain")
|
14
|
+
interface.put_attributes('MyDomain', 'Item123', {'color'=>['red','brick','garnet']})
|
15
|
+
|
16
|
+
attributes = interface.get_attributes('MyDomain', 'Item123')
|
17
|
+
puts "Item123 = #{attributes.inspect}"
|
18
|
+
|
19
|
+
items = interface.select("select color from MyDomain where color = 'brick'")
|
20
|
+
puts "Items = #{items.inspect}"
|
21
|
+
|
22
|
+
interface.delete_domain("MyDomain")
|
23
|
+
end
|
24
|
+
|
25
|
+
## Note on Patches/Pull Requests
|
26
|
+
|
27
|
+
* Fork the project.
|
28
|
+
* Make your feature addition or bug fix.
|
29
|
+
* Add tests for it. This is important so I don't break it in a
|
30
|
+
future version unintentionally.
|
31
|
+
* Commit, do not mess with rakefile, version, or history.
|
32
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
33
|
+
* Send me a pull request. Bonus points for topic branches.
|
34
|
+
|
35
|
+
## Copyright
|
36
|
+
|
37
|
+
Copyright (c) 2010 JT Archie. See LICENSE for details.
|
data/Rakefile
CHANGED
@@ -1,54 +1,14 @@
|
|
1
|
-
require '
|
2
|
-
require '
|
1
|
+
require 'bundler'
|
2
|
+
require 'rspec/core/rake_task'
|
3
3
|
|
4
|
-
|
5
|
-
require 'jeweler'
|
6
|
-
Jeweler::Tasks.new do |gem|
|
7
|
-
gem.name = "simplydb"
|
8
|
-
gem.summary = %Q{A minimal interface to Amazon SimpleDB.}
|
9
|
-
gem.description = %Q{A minimal interface to Amazon SimpleDB that has separation of interfaces. From the low level HTTP request access to high level Ruby abstraction ORM.}
|
10
|
-
gem.email = "jtarchie@gmail.com"
|
11
|
-
gem.homepage = "http://github.com/jtarchie/simplydb"
|
12
|
-
gem.authors = ["JT Archie"]
|
13
|
-
gem.add_development_dependency "rspec", ">= 1.2.9"
|
14
|
-
gem.add_dependency "typhoeus", ">= 0.1.27"
|
15
|
-
gem.add_dependency "nokogiri", ">= 1.4.2"
|
16
|
-
gem.add_dependency "uuidtools", ">= 2.1.1"
|
17
|
-
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
18
|
-
end
|
19
|
-
Jeweler::GemcutterTasks.new
|
20
|
-
rescue LoadError
|
21
|
-
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
22
|
-
end
|
23
|
-
|
24
|
-
require 'spec/rake/spectask'
|
25
|
-
Spec::Rake::SpecTask.new(:spec) do |spec|
|
26
|
-
spec.libs << 'lib' << 'spec'
|
27
|
-
spec.spec_files = FileList['spec/**/*_spec.rb']
|
28
|
-
end
|
29
|
-
|
30
|
-
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
31
|
-
spec.libs << 'lib' << 'spec'
|
32
|
-
spec.pattern = 'spec/**/*_spec.rb'
|
33
|
-
spec.rcov = true
|
34
|
-
end
|
4
|
+
Bundler::GemHelper.install_tasks
|
35
5
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
exec("irb -I lib/ -r 'simplydb' -r 'simplydb/record/base'")
|
6
|
+
desc "Run specs"
|
7
|
+
task :spec do
|
8
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
9
|
+
t.rspec_opts = %w{--colour --format progress}
|
10
|
+
t.pattern = 'spec/*_spec.rb'
|
11
|
+
end
|
43
12
|
end
|
44
|
-
task :console => :irb
|
45
13
|
|
46
|
-
|
47
|
-
Rake::RDocTask.new do |rdoc|
|
48
|
-
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
49
|
-
|
50
|
-
rdoc.rdoc_dir = 'rdoc'
|
51
|
-
rdoc.title = "simplydb #{version}"
|
52
|
-
rdoc.rdoc_files.include('README*')
|
53
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
54
|
-
end
|
14
|
+
task :default => :spec
|
data/lib/simplydb.rb
CHANGED
data/lib/simplydb/client.rb
CHANGED
@@ -1,66 +1,79 @@
|
|
1
1
|
require 'openssl'
|
2
2
|
require 'digest/sha1'
|
3
3
|
require 'base64'
|
4
|
-
require '
|
5
|
-
require 'simplydb/clients/typhoeus'
|
4
|
+
require 'rest_client'
|
6
5
|
|
7
6
|
module SimplyDB
|
8
7
|
class Client
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
@options[:
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
8
|
+
attr_accessor :options, :http_client
|
9
|
+
|
10
|
+
def initialize(options = {})
|
11
|
+
@options = {
|
12
|
+
:protocol => 'https://',
|
13
|
+
:host => 'sdb.amazonaws.com',
|
14
|
+
:port => 443,
|
15
|
+
:path => "/",
|
16
|
+
:signature_version => '2',
|
17
|
+
:version => '2009-04-15',
|
18
|
+
:signature_method => 'HmacSHA256',
|
19
|
+
}.merge(options)
|
20
|
+
end
|
21
|
+
|
22
|
+
def base_url
|
23
|
+
"#{@options[:protocol]}#{@options[:host]}:#{@options[:port]}#{@options[:path]}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def string_to_sign(method, params)
|
27
|
+
return "#{method.to_s.upcase}\n#{options[:host]}\n/\n" + escape_hash(params)
|
28
|
+
end
|
29
|
+
|
30
|
+
def generate_signature(method, params)
|
31
|
+
Base64.encode64(
|
32
|
+
OpenSSL::HMAC.digest(
|
33
|
+
OpenSSL::Digest::Digest.new('sha256'),
|
34
|
+
@options[:secret_key],
|
35
|
+
string_to_sign(method, params)
|
36
|
+
)
|
37
|
+
).chomp
|
38
|
+
end
|
39
|
+
|
40
|
+
def params_with_signature(method, params)
|
41
|
+
params.merge!({
|
42
|
+
'AWSAccessKeyId' => @options[:access_key],
|
43
|
+
'SignatureVersion' => @options[:signature_version],
|
44
|
+
'Timestamp' => Time.now.iso8601,
|
45
|
+
'Version' => @options[:version],
|
46
|
+
'SignatureMethod' => @options[:signature_method]
|
47
|
+
})
|
48
|
+
params['Signature'] = generate_signature(method, params)
|
49
|
+
params
|
50
|
+
end
|
51
|
+
|
52
|
+
def call(method, params, &block)
|
53
|
+
params = params_with_signature(method, params)
|
54
|
+
response = case method.to_sym
|
55
|
+
# when :get
|
56
|
+
# RestClient.get(base_url << "?#{escape_hash(params)}")
|
57
|
+
when :post
|
58
|
+
RestClient.post(base_url, params)
|
59
|
+
else
|
60
|
+
raise "Not support request method #{method}"
|
61
|
+
end
|
62
|
+
block.call(response.body)
|
63
|
+
rescue RestClient::BadRequest => e
|
64
|
+
block.call(e.response.body)
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def escape_value(string)
|
70
|
+
string.gsub(/([^ a-zA-Z0-9_.-]+)/n) do
|
71
|
+
'%' + $1.unpack('H2' * $1.size).join('%').upcase
|
72
|
+
end.gsub(' ', '%20')
|
73
|
+
end
|
74
|
+
|
75
|
+
def escape_hash(params = {})
|
76
|
+
return params.collect{|k,v| [k.to_s, v.to_s]}.sort.collect { |key, value| [escape_value(key), escape_value(value)].join('=') }.join('&')
|
77
|
+
end
|
64
78
|
end
|
65
|
-
end
|
66
79
|
end
|
data/lib/simplydb/error.rb
CHANGED
@@ -1,60 +1,65 @@
|
|
1
1
|
module SimplyDB
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
class ConditionalCheckFailed < RuntimeError; end
|
9
|
-
class ExistsAndExpectedValue < RuntimeError; end
|
10
|
-
class FeatureDeprecated < RuntimeError; end
|
11
|
-
class IncompleteExpectedExpression < RuntimeError; end
|
12
|
-
class InternalError < RuntimeError; end
|
13
|
-
class InvalidAction < RuntimeError; end
|
14
|
-
class InvalidHTTPAuthHeader < RuntimeError; end
|
15
|
-
class InvalidHttpRequest < RuntimeError; end
|
16
|
-
class InvalidLiteral < RuntimeError; end
|
17
|
-
class InvalidNextToken < RuntimeError; end
|
18
|
-
class InvalidNumberPredicates < RuntimeError; end
|
19
|
-
class InvalidNumberValueTests < RuntimeError; end
|
20
|
-
class InvalidParameterCombination < RuntimeError; end
|
21
|
-
class InvalidParameterValue < RuntimeError; end
|
22
|
-
class InvalidQueryExpression < RuntimeError; end
|
23
|
-
class InvalidResponseGroups < RuntimeError; end
|
24
|
-
class InvalidService < RuntimeError; end
|
25
|
-
class InvalidSOAPRequest < RuntimeError; end
|
26
|
-
class InvalidSortExpression < RuntimeError; end
|
27
|
-
class InvalidURI < RuntimeError; end
|
28
|
-
class InvalidWSAddressingProperty < RuntimeError; end
|
29
|
-
class InvalidWSDLVersion < RuntimeError; end
|
30
|
-
class MalformedSOAPSignature < RuntimeError; end
|
31
|
-
class MissingAction < RuntimeError; end
|
32
|
-
class MissingParameter < RuntimeError; end
|
33
|
-
class MissingWSAddressingProperty < RuntimeError; end
|
34
|
-
class MultipleExistsConditions < RuntimeError; end
|
35
|
-
class MultipleExpectedNames < RuntimeError; end
|
36
|
-
class MultipleExpectedValues < RuntimeError; end
|
37
|
-
class MultiValuedAttribute < RuntimeError; end
|
38
|
-
class NoSuchDomain < RuntimeError; end
|
39
|
-
class NoSuchVersion < RuntimeError; end
|
40
|
-
class NotYetImplemented < RuntimeError; end
|
41
|
-
class NumberDomainsExceeded < RuntimeError; end
|
42
|
-
class NumberDomainAttributesExceeded < RuntimeError; end
|
43
|
-
class NumberDomainBytesExceeded < RuntimeError; end
|
44
|
-
class NumberItemAttributesExceeded < RuntimeError; end
|
45
|
-
class NumberSubmittedAttributesExceeded < RuntimeError; end
|
46
|
-
class NumberSubmittedItemsExceeded < RuntimeError; end
|
47
|
-
class RequestExpired < RuntimeError; end
|
48
|
-
class RequestTimeout < RuntimeError; end
|
49
|
-
class ServiceUnavailable < RuntimeError; end
|
50
|
-
class TooManyRequestedAttributes < RuntimeError; end
|
51
|
-
class UnsupportedHttpVerb < RuntimeError; end
|
52
|
-
class UnsupportedNextToken < RuntimeError; end
|
53
|
-
class URITooLong < RuntimeError; end
|
54
|
-
|
55
|
-
#Standard AWS errors
|
56
|
-
class SignatureDoesNotMatch < RuntimeError; end
|
57
|
-
class InvalidClientTokenId < RuntimeError; end
|
58
|
-
class InvalidRequest < RuntimeError; end
|
2
|
+
class Error < RuntimeError
|
3
|
+
attr_accessor :http_status_code, :name
|
4
|
+
def initialize(name, http_status_code)
|
5
|
+
@name = name
|
6
|
+
@http_status_code = http_status_code
|
7
|
+
end
|
59
8
|
end
|
9
|
+
|
10
|
+
AccessFailure = Error.new("AccessFailure",403)
|
11
|
+
AttributeDoesNotExist = Error.new("AttributeDoesNotExist",404)
|
12
|
+
AuthFailure = Error.new("AuthFailure",403)
|
13
|
+
AuthMissingFailure = Error.new("AuthMissingFailure",403)
|
14
|
+
ConditionalCheckFailed = Error.new("ConditionalCheckFailed",409)
|
15
|
+
ExistsAndExpectedValue = Error.new("ExistsAndExpectedValue",400)
|
16
|
+
FeatureDeprecated = Error.new("FeatureDeprecated",400)
|
17
|
+
IncompleteExpectedExpression = Error.new("IncompleteExpectedExpression",400)
|
18
|
+
InternalError = Error.new("InternalError",500)
|
19
|
+
InvalidAction = Error.new("InvalidAction",400)
|
20
|
+
InvalidHTTPAuthHeader = Error.new("InvalidHTTPAuthHeader",400)
|
21
|
+
InvalidHttpRequest = Error.new("InvalidHttpRequest",400)
|
22
|
+
InvalidLiteral = Error.new("InvalidLiteral",400)
|
23
|
+
InvalidNextToken = Error.new("InvalidNextToken",400)
|
24
|
+
InvalidNumberPredicates = Error.new("InvalidNumberPredicates",400)
|
25
|
+
InvalidNumberValueTests = Error.new("InvalidNumberValueTests",400)
|
26
|
+
InvalidParameterCombination = Error.new("InvalidParameterCombination",400)
|
27
|
+
InvalidParameterValue = Error.new("InvalidParameterValue",400)
|
28
|
+
InvalidQueryExpression = Error.new("InvalidQueryExpression",400)
|
29
|
+
InvalidResponseGroups = Error.new("InvalidResponseGroups",400)
|
30
|
+
InvalidService = Error.new("InvalidService",400)
|
31
|
+
InvalidSOAPRequest = Error.new("InvalidSOAPRequest",400)
|
32
|
+
InvalidSortExpression = Error.new("InvalidSortExpression",400)
|
33
|
+
InvalidURI = Error.new("InvalidURI",400)
|
34
|
+
InvalidWSAddressingProperty = Error.new("InvalidWSAddressingProperty",400)
|
35
|
+
InvalidWSDLVersion = Error.new("InvalidWSDLVersion",400)
|
36
|
+
MalformedSOAPSignature = Error.new("MalformedSOAPSignature",403)
|
37
|
+
MissingAction = Error.new("MissingAction",400)
|
38
|
+
MissingParameter = Error.new("MissingParameter",400)
|
39
|
+
MissingWSAddressingProperty = Error.new("MissingWSAddressingProperty",400)
|
40
|
+
MultipleExistsConditions = Error.new("MultipleExistsConditions",400)
|
41
|
+
MultipleExpectedNames = Error.new("MultipleExpectedNames",400)
|
42
|
+
MultipleExpectedValues = Error.new("MultipleExpectedValues",400)
|
43
|
+
MultiValuedAttribute = Error.new("MultiValuedAttribute",409)
|
44
|
+
NoSuchDomain = Error.new("NoSuchDomain",400)
|
45
|
+
NoSuchVersion = Error.new("NoSuchVersion",400)
|
46
|
+
NotYetImplemented = Error.new("NotYetImplemented",401)
|
47
|
+
NumberDomainsExceeded = Error.new("NumberDomainsExceeded",409)
|
48
|
+
NumberDomainAttributesExceeded = Error.new("NumberDomainAttributesExceeded",409)
|
49
|
+
NumberDomainBytesExceeded = Error.new("NumberDomainBytesExceeded",409)
|
50
|
+
NumberItemAttributesExceeded = Error.new("NumberItemAttributesExceeded",409)
|
51
|
+
NumberSubmittedAttributesExceeded = Error.new("NumberSubmittedAttributesExceeded",409)
|
52
|
+
NumberSubmittedItemsExceeded = Error.new("NumberSubmittedItemsExceeded",409)
|
53
|
+
RequestExpired = Error.new("RequestExpired",400)
|
54
|
+
RequestTimeout = Error.new("RequestTimeout",408)
|
55
|
+
ServiceUnavailable = Error.new("ServiceUnavailable",503)
|
56
|
+
TooManyRequestedAttributes = Error.new("TooManyRequestedAttributes",400)
|
57
|
+
UnsupportedHttpVerb = Error.new("UnsupportedHttpVerb",400)
|
58
|
+
UnsupportedNextToken = Error.new("UnsupportedNextToken",400)
|
59
|
+
URITooLong = Error.new("URITooLong",400)
|
60
|
+
|
61
|
+
#Standard AWS errors
|
62
|
+
SignatureDoesNotMatch = Error.new("SignatureDoesNotMatch",400)
|
63
|
+
InvalidClientTokenId = Error.new("InvalidClientTokenId",400)
|
64
|
+
InvalidRequest = Error.new("InvalidRequest",400)
|
60
65
|
end
|
data/lib/simplydb/interface.rb
CHANGED
@@ -7,43 +7,35 @@ module SimplyDB
|
|
7
7
|
@options = {}.merge(options)
|
8
8
|
@client = SimplyDB::Client.new(options)
|
9
9
|
end
|
10
|
-
|
11
|
-
def create_domain(name
|
10
|
+
|
11
|
+
def create_domain(name)
|
12
12
|
call({'Action' => 'CreateDomain', 'DomainName' => name}) do |doc|
|
13
|
-
|
14
|
-
block.call(ret_val) if block_given?
|
15
|
-
ret_val
|
13
|
+
doc.css("CreateDomainResponse").length > 0
|
16
14
|
end
|
17
15
|
end
|
18
|
-
|
19
|
-
def delete_domain(name
|
16
|
+
|
17
|
+
def delete_domain(name)
|
20
18
|
call({'Action' => 'DeleteDomain', 'DomainName' => name}) do |doc|
|
21
|
-
|
22
|
-
block.call(ret_val) if block_given?
|
23
|
-
ret_val
|
19
|
+
doc.css("DeleteDomainResponse").length > 0
|
24
20
|
end
|
25
21
|
end
|
26
|
-
|
27
|
-
def list_domains
|
22
|
+
|
23
|
+
def list_domains
|
28
24
|
call({'Action' => 'ListDomains'}) do |doc|
|
29
|
-
|
30
|
-
block.call(domains) if block_given?
|
31
|
-
domains
|
25
|
+
doc.css('DomainName').collect{|d| d.text}
|
32
26
|
end
|
33
27
|
end
|
34
|
-
|
35
|
-
def domain_metadata(name
|
28
|
+
|
29
|
+
def domain_metadata(name)
|
36
30
|
call({'Action' => 'DomainMetadata','DomainName' => name}) do |doc|
|
37
|
-
|
31
|
+
doc.css("DomainMetadataResult").first.children.inject({}) do |memo, child|
|
38
32
|
memo[child.name] = child.text
|
39
33
|
memo
|
40
34
|
end
|
41
|
-
block.call(attributes) if block_given?
|
42
|
-
attributes
|
43
35
|
end
|
44
36
|
end
|
45
|
-
|
46
|
-
def put_attributes(name, id, attributes = {}, expected = {}, replace = false
|
37
|
+
|
38
|
+
def put_attributes(name, id, attributes = {}, expected = {}, replace = false)
|
47
39
|
params = define_attributes(attributes, expected, replace)
|
48
40
|
params.merge!({
|
49
41
|
'DomainName' => name,
|
@@ -51,13 +43,11 @@ module SimplyDB
|
|
51
43
|
'Action' => 'PutAttributes'
|
52
44
|
})
|
53
45
|
call(params) do |doc|
|
54
|
-
|
55
|
-
block.call(ret_val) if block_given?
|
56
|
-
ret_val
|
46
|
+
doc.css("PutAttributesResponse").length > 0
|
57
47
|
end
|
58
48
|
end
|
59
|
-
|
60
|
-
def batch_put_attributes(name, items = {}
|
49
|
+
|
50
|
+
def batch_put_attributes(name, items = {})
|
61
51
|
params = {'DomainName' => name, 'ActionName' => 'BatchPutAttributes'}
|
62
52
|
items.keys.each_with_index do |key, i|
|
63
53
|
params["Item.#{i}.ItemName"] = key
|
@@ -72,13 +62,11 @@ module SimplyDB
|
|
72
62
|
end
|
73
63
|
end
|
74
64
|
call(params) do |doc|
|
75
|
-
|
76
|
-
block.call(ret_val) if block_given?
|
77
|
-
ret_val
|
65
|
+
doc.css("BatchPutAttributesResponse").length > 0
|
78
66
|
end
|
79
67
|
end
|
80
|
-
|
81
|
-
def delete_attributes(name, id, attributes = {}, expected = {}
|
68
|
+
|
69
|
+
def delete_attributes(name, id, attributes = {}, expected = {})
|
82
70
|
params = define_attributes(attributes, expected)
|
83
71
|
params.merge!({
|
84
72
|
'DomainName' => name,
|
@@ -86,23 +74,21 @@ module SimplyDB
|
|
86
74
|
'Action' => 'DeleteAttributes'
|
87
75
|
})
|
88
76
|
call(params) do |doc|
|
89
|
-
|
90
|
-
block.call(ret_val) if block_given?
|
91
|
-
ret_val
|
77
|
+
doc.css("DeleteAttributesResponse").length > 0
|
92
78
|
end
|
93
79
|
end
|
94
|
-
|
95
|
-
def get_attributes(name, id, wanted_attributes = [], consistent_read = false
|
80
|
+
|
81
|
+
def get_attributes(name, id, wanted_attributes = [], consistent_read = false)
|
96
82
|
params = {
|
97
83
|
'Action' => 'GetAttributes',
|
98
84
|
'DomainName' => name,
|
99
85
|
'ItemName' => id,
|
100
|
-
'ConsistentRead' => consistent_read.to_s,
|
86
|
+
'ConsistentRead' => consistent_read.to_s,
|
101
87
|
}
|
102
88
|
wanted_attributes.each_with_index {|name, index| params["AttributeName.#{index}"] = name}
|
103
89
|
|
104
90
|
call(params) do |doc|
|
105
|
-
|
91
|
+
doc.css("Attribute").inject({}) do |memo, attribute|
|
106
92
|
name = attribute.css("Name").first.text
|
107
93
|
value = attribute.css("Value").first.text
|
108
94
|
if memo.has_key?(name)
|
@@ -113,12 +99,10 @@ module SimplyDB
|
|
113
99
|
end
|
114
100
|
memo
|
115
101
|
end
|
116
|
-
block.call(attributes) if block_given?
|
117
|
-
attributes
|
118
102
|
end
|
119
103
|
end
|
120
|
-
|
121
|
-
def select(expression, consistent_read = false, next_token = nil
|
104
|
+
|
105
|
+
def select(expression, consistent_read = false, next_token = nil)
|
122
106
|
params = {
|
123
107
|
'Action' => 'Select',
|
124
108
|
'SelectExpression' => expression,
|
@@ -126,9 +110,9 @@ module SimplyDB
|
|
126
110
|
}
|
127
111
|
params['NextToken'] = next_token unless next_token.nil?
|
128
112
|
call(params) do |doc|
|
129
|
-
|
130
|
-
item_name =
|
131
|
-
|
113
|
+
doc.css("SelectResponse SelectResult Item").collect do |element|
|
114
|
+
item_name = element.css("Name").first.text
|
115
|
+
item = element.css("Attribute").inject({}) do |attributes, attribute|
|
132
116
|
attribute_name = attribute.css("Name").first.text
|
133
117
|
attribute_value = attribute.css("Value").first.text
|
134
118
|
if attributes.has_key?(attribute_name)
|
@@ -139,13 +123,11 @@ module SimplyDB
|
|
139
123
|
end
|
140
124
|
attributes
|
141
125
|
end
|
142
|
-
|
126
|
+
{item_name => item}
|
143
127
|
end
|
144
|
-
block.call(ret_val) if block_given?
|
145
|
-
ret_val
|
146
128
|
end
|
147
129
|
end
|
148
|
-
|
130
|
+
|
149
131
|
private
|
150
132
|
def define_attributes(attributes = {}, expected = {}, replace = false)
|
151
133
|
params = {}
|
@@ -154,7 +136,7 @@ module SimplyDB
|
|
154
136
|
v.each do |value|
|
155
137
|
params["Attribute.#{index}.Name"] = k
|
156
138
|
params["Attribute.#{index}.Value"] = value
|
157
|
-
params["Attribute.#{index}.Replace"] = "
|
139
|
+
params["Attribute.#{index}.Replace"] = "true" if replace
|
158
140
|
index += 1
|
159
141
|
end
|
160
142
|
index
|
@@ -178,9 +160,9 @@ module SimplyDB
|
|
178
160
|
end
|
179
161
|
index
|
180
162
|
}
|
181
|
-
|
163
|
+
params
|
182
164
|
end
|
183
|
-
|
165
|
+
|
184
166
|
def call(params = {}, attempts = 3, &block)
|
185
167
|
@client.call(:post, params) do |body|
|
186
168
|
begin
|
@@ -194,7 +176,7 @@ module SimplyDB
|
|
194
176
|
@next_token = doc.css("NextToken").first.text unless doc.css("NextToken").empty?
|
195
177
|
block.call(doc)
|
196
178
|
end
|
197
|
-
rescue SimplyDB::Error::ServiceUnavailable => e
|
179
|
+
rescue SimplyDB::Error::ServiceUnavailable, RestClient::ServiceUnavailable => e
|
198
180
|
if attempts > 0
|
199
181
|
call(params, attempts - 1, &block)
|
200
182
|
else
|