sucker 0.1.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.
- data/LICENSE +22 -0
- data/README.textile +19 -0
- data/lib/sucker/request.rb +112 -0
- data/lib/sucker.rb +14 -0
- data/spec/integration/item_lookup_spec.rb +53 -0
- data/spec/integration/seller_listing_search_spec.rb +29 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/support/amazon_credentials.rb +3 -0
- data/spec/support/curb_stubber.rb +7 -0
- data/spec/unit/sucker/request_spec.rb +159 -0
- data/spec/unit/sucker_spec.rb +9 -0
- metadata +151 -0
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
(The MIT License)
|
2
|
+
|
3
|
+
Copyright (c) 2009 Paper Cavalier
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
'Software'), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
19
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
20
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
21
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
22
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.textile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
h1. Sucker
|
2
|
+
|
3
|
+
Sucker is a thin Ruby wrapper to the Amazon Product Advertising API. It's built on Curb, which is great for querying Amazon on multiple network ports.
|
4
|
+
|
5
|
+
@sucker = Sucker.new(
|
6
|
+
:locale => "us",
|
7
|
+
:key => "key",
|
8
|
+
:secret => "secret")
|
9
|
+
|
10
|
+
@sucker.curl { |curl| curl.interface = "eth2" }
|
11
|
+
|
12
|
+
@sucker.parameters.merge!({
|
13
|
+
"Operation" => "ItemLookup",
|
14
|
+
"IdType" => "ASIN",
|
15
|
+
"ItemId" => "0816614024" })
|
16
|
+
@sucker.fetch
|
17
|
+
p @sucker.to_h # Now, do something with that hash!
|
18
|
+
|
19
|
+
!http://upload.wikimedia.org/wikipedia/commons/a/af/Vacuum_cleaner.jpg!
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# = Sucker
|
2
|
+
# Sucker is a thin Ruby wrapper to the {Amazon Product Advertising API}[http://docs.amazonwebservices.com/AWSECommerceService/latest/DG/].
|
3
|
+
#
|
4
|
+
module Sucker
|
5
|
+
class Request
|
6
|
+
HOSTS = {
|
7
|
+
:us => 'ecs.amazonaws.com',
|
8
|
+
:uk => 'ecs.amazonaws.co.uk',
|
9
|
+
:de => 'ecs.amazonaws.de',
|
10
|
+
:ca => 'ecs.amazonaws.ca',
|
11
|
+
:fr => 'ecs.amazonaws.fr',
|
12
|
+
:jp => 'ecs.amazonaws.jp' }
|
13
|
+
|
14
|
+
# The Amazon locale to query
|
15
|
+
attr_accessor :locale
|
16
|
+
|
17
|
+
# The Amazon secret access key
|
18
|
+
attr_accessor :secret
|
19
|
+
|
20
|
+
# The hash of parameters to query Amazon with
|
21
|
+
attr_accessor :parameters
|
22
|
+
|
23
|
+
def initialize(args)
|
24
|
+
self.parameters = {
|
25
|
+
"Service" => "AWSECommerceService",
|
26
|
+
"Version" => Sucker::AMAZON_API_VERSION
|
27
|
+
}
|
28
|
+
|
29
|
+
args.each { |k, v| send("#{k}=", v) }
|
30
|
+
end
|
31
|
+
|
32
|
+
# A reusable, configurable cURL object
|
33
|
+
def curl
|
34
|
+
@curl ||= Curl::Easy.new
|
35
|
+
|
36
|
+
yield @curl if block_given?
|
37
|
+
|
38
|
+
@curl
|
39
|
+
end
|
40
|
+
|
41
|
+
# Hits Amazon with an API request
|
42
|
+
def fetch
|
43
|
+
return nil if !valid?
|
44
|
+
|
45
|
+
curl.url = uri.to_s
|
46
|
+
curl.perform
|
47
|
+
end
|
48
|
+
|
49
|
+
# A helper method that sets the AWS Access Key ID
|
50
|
+
def key=(key)
|
51
|
+
parameters["AWSAccessKeyId"] = key
|
52
|
+
end
|
53
|
+
|
54
|
+
# Returns a hash of the response
|
55
|
+
def to_h
|
56
|
+
Crack::XML.parse(curl.body_str)
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
# Escapes parameters and concatenates them into a query string
|
62
|
+
def build_query
|
63
|
+
parameters.
|
64
|
+
sort.
|
65
|
+
collect do |k, v|
|
66
|
+
"#{CGI.escape(k)}=" + CGI.escape(v.is_a?(Array) ? v.join(",") : v)
|
67
|
+
end.
|
68
|
+
join("&")
|
69
|
+
end
|
70
|
+
|
71
|
+
def digest
|
72
|
+
OpenSSL::Digest::Digest.new("sha256")
|
73
|
+
end
|
74
|
+
|
75
|
+
def host
|
76
|
+
HOSTS[locale.to_sym]
|
77
|
+
end
|
78
|
+
|
79
|
+
def path
|
80
|
+
"/onca/xml"
|
81
|
+
end
|
82
|
+
|
83
|
+
# Returns a signed and timestamped query string
|
84
|
+
def sign_query
|
85
|
+
timestamp_parameters
|
86
|
+
|
87
|
+
query = build_query
|
88
|
+
|
89
|
+
string = ["GET", host, path, query].join("\n")
|
90
|
+
hmac = OpenSSL::HMAC.digest(digest, secret, string)
|
91
|
+
|
92
|
+
query + "&Signature=" + CGI.escape([hmac].pack("m").chomp)
|
93
|
+
end
|
94
|
+
|
95
|
+
def uri
|
96
|
+
URI::HTTP.build(
|
97
|
+
:host => host,
|
98
|
+
:path => path,
|
99
|
+
:query => sign_query)
|
100
|
+
end
|
101
|
+
|
102
|
+
# Timestamps the parameters
|
103
|
+
def timestamp_parameters
|
104
|
+
self.parameters["Timestamp"] = Time.now.utc.strftime('%Y-%m-%dT%H:%M:%SZ')
|
105
|
+
end
|
106
|
+
|
107
|
+
# Returns true if request has key, secret, and a valid locale set
|
108
|
+
def valid?
|
109
|
+
!!locale && !!HOSTS[locale.to_sym] && !!secret && !!parameters["AWSAccessKeyId"]
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
data/lib/sucker.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
module Sucker
|
2
|
+
VERSION = '0.1.0'.freeze
|
3
|
+
AMAZON_API_VERSION = '2009-11-01'.freeze
|
4
|
+
|
5
|
+
class SuckerError < StandardError; end
|
6
|
+
|
7
|
+
def self.new(args={})
|
8
|
+
Sucker::Request.new(args)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
require 'cgi'
|
13
|
+
require 'sucker/request'
|
14
|
+
require 'crack/xml'
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module Sucker
|
4
|
+
describe "Item Lookup" do
|
5
|
+
before do
|
6
|
+
@sucker = Sucker.new(
|
7
|
+
:locale => "us",
|
8
|
+
:key => amazon["key"],
|
9
|
+
:secret => amazon["secret"])
|
10
|
+
|
11
|
+
# @sucker.curl { |curl| curl.verbose = true }
|
12
|
+
|
13
|
+
@sucker.parameters.merge!({
|
14
|
+
"Operation" => "ItemLookup",
|
15
|
+
"IdType" => "ASIN"})
|
16
|
+
end
|
17
|
+
|
18
|
+
context "single item" do
|
19
|
+
before do
|
20
|
+
@sucker.parameters.merge!({
|
21
|
+
"ItemId" => "0816614024" })
|
22
|
+
@sucker.fetch
|
23
|
+
@item = @sucker.to_h["ItemLookupResponse"]["Items"]["Item"]
|
24
|
+
end
|
25
|
+
|
26
|
+
it "returns an item" do
|
27
|
+
@item.should be_an_instance_of Hash
|
28
|
+
end
|
29
|
+
|
30
|
+
it "includes an ASIN string" do
|
31
|
+
@item["ASIN"].should eql "0816614024"
|
32
|
+
end
|
33
|
+
|
34
|
+
it "includes the item attributes" do
|
35
|
+
@item["ItemAttributes"].should be_an_instance_of Hash
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context "multiple items" do
|
40
|
+
before do
|
41
|
+
@sucker.parameters.merge!({
|
42
|
+
"ItemId" => ["0816614024", "0143105825"] })
|
43
|
+
@sucker.fetch
|
44
|
+
@items = @sucker.to_h["ItemLookupResponse"]["Items"]["Item"]
|
45
|
+
end
|
46
|
+
|
47
|
+
it "returns two items" do
|
48
|
+
@items.should be_an_instance_of Array
|
49
|
+
@items.size.should eql 2
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module Sucker
|
4
|
+
describe "Seller Listing Search" do
|
5
|
+
before do
|
6
|
+
@sucker = Sucker.new(
|
7
|
+
:locale => "us",
|
8
|
+
:key => amazon["key"],
|
9
|
+
:secret => amazon["secret"])
|
10
|
+
|
11
|
+
# @sucker.curl { |curl| curl.verbose = true }
|
12
|
+
|
13
|
+
@sucker.parameters.merge!({
|
14
|
+
"Operation" => "SellerListingSearch",
|
15
|
+
"SellerId" => "A31N271NVIORU3"})
|
16
|
+
@sucker.fetch
|
17
|
+
@listings = @sucker.to_h["SellerListingSearchResponse"]["SellerListings"]
|
18
|
+
end
|
19
|
+
|
20
|
+
it "returns page count" do
|
21
|
+
@listings["TotalPages"].to_i.should be > 0
|
22
|
+
end
|
23
|
+
|
24
|
+
it "returns listings" do
|
25
|
+
@listings["SellerListing"].size.should be > 0
|
26
|
+
@listings["SellerListing"].first.has_key?("Price").should be_true
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,159 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module Sucker
|
4
|
+
describe "Request" do
|
5
|
+
before do
|
6
|
+
@sucker = Sucker.new
|
7
|
+
end
|
8
|
+
|
9
|
+
context "public" do
|
10
|
+
context ".new" do
|
11
|
+
it "sets default parameters" do
|
12
|
+
default_parameters = {
|
13
|
+
"Service" => "AWSECommerceService",
|
14
|
+
"Version" => Sucker::AMAZON_API_VERSION }
|
15
|
+
@sucker.parameters.should eql default_parameters
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context "#curl" do
|
20
|
+
it "returns a cURL object" do
|
21
|
+
@sucker.curl.should be_an_instance_of Curl::Easy
|
22
|
+
end
|
23
|
+
|
24
|
+
it "configures the cURL object" do
|
25
|
+
@sucker.curl.interface.should be_nil
|
26
|
+
|
27
|
+
@sucker.curl do |curl|
|
28
|
+
curl.interface = "eth1"
|
29
|
+
end
|
30
|
+
|
31
|
+
@sucker.curl.interface.should eql "eth1"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "#fetch" do
|
36
|
+
it "returns nil if valid? returns false" do
|
37
|
+
@sucker.stub!(:valid?).and_return(false)
|
38
|
+
@sucker.fetch.should be_nil
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context "#to_h" do
|
43
|
+
before do
|
44
|
+
@sucker.curl.stub!(:body_str).and_return(fixture("single_item_lookup.us"))
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should return a hash" do
|
48
|
+
@sucker.to_h.should be_an_instance_of Hash
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context "private" do
|
54
|
+
context "#build_query" do
|
55
|
+
it "canonicalizes parameters" do
|
56
|
+
query = @sucker.send(:build_query)
|
57
|
+
query.should eql "Service=AWSECommerceService&Version=#{Sucker::AMAZON_API_VERSION}"
|
58
|
+
end
|
59
|
+
|
60
|
+
it "sorts parameters" do
|
61
|
+
@sucker.parameters["Foo"] = "bar"
|
62
|
+
query = @sucker.send(:build_query)
|
63
|
+
query.should match /^Foo=bar/
|
64
|
+
end
|
65
|
+
|
66
|
+
it "converts a parameter whose value is an array to a string" do
|
67
|
+
@sucker.parameters["Foo"] = ["bar", "baz"]
|
68
|
+
query = @sucker.send(:build_query)
|
69
|
+
query.should match /^Foo=bar%2Cbaz/
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context "#digest" do
|
74
|
+
it "returns a digest object" do
|
75
|
+
@sucker.send(:digest).should be_an_instance_of OpenSSL::Digest::Digest
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context "#key=" do
|
80
|
+
it "sets the Amazon AWS access key in the parameters" do
|
81
|
+
@sucker.key = "key"
|
82
|
+
@sucker.parameters["AWSAccessKeyId"].should eql "key"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context "#host" do
|
87
|
+
it "returns a host" do
|
88
|
+
@sucker.locale = "us"
|
89
|
+
@sucker.send(:host).should eql "ecs.amazonaws.com"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context "#path" do
|
94
|
+
it "returns a path" do
|
95
|
+
@sucker.send(:path).should eql "/onca/xml"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context "#sign_query" do
|
100
|
+
it "returns a signed query string" do
|
101
|
+
@sucker.secret = "secret"
|
102
|
+
@sucker.locale = "us"
|
103
|
+
query = @sucker.send :sign_query
|
104
|
+
query.should match /&Signature=.*/
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context "#timestamp_parameters" do
|
109
|
+
it "upserts a timestamp to the parameters" do
|
110
|
+
@sucker.send :timestamp_parameters
|
111
|
+
@sucker.parameters["Timestamp"].should match /^\d+-\d+-\d+T\d+:\d+:\d+Z$/
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
context "#uri" do
|
116
|
+
it "returns the URI with which to query Amazon" do
|
117
|
+
@sucker.key = "key"
|
118
|
+
@sucker.locale = "us"
|
119
|
+
@sucker.secret = "secret"
|
120
|
+
@sucker.send(:uri).should be_an_instance_of URI::HTTP
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
context "valid?" do
|
125
|
+
it "returns true if key, secret, and a valid locale are set" do
|
126
|
+
@sucker.key = "key"
|
127
|
+
@sucker.locale = "us"
|
128
|
+
@sucker.secret = "secret"
|
129
|
+
@sucker.send(:valid?).should be_true
|
130
|
+
end
|
131
|
+
|
132
|
+
it "returns false if key is not set" do
|
133
|
+
@sucker.locale = "us"
|
134
|
+
@sucker.secret = "secret"
|
135
|
+
@sucker.send(:valid?).should be_false
|
136
|
+
end
|
137
|
+
|
138
|
+
it "returns false if secret is not set" do
|
139
|
+
@sucker.locale = "us"
|
140
|
+
@sucker.key = "key"
|
141
|
+
@sucker.send(:valid?).should be_false
|
142
|
+
end
|
143
|
+
|
144
|
+
it "returns false if locale is not set" do
|
145
|
+
@sucker.key = "key"
|
146
|
+
@sucker.secret = "secret"
|
147
|
+
@sucker.send(:valid?).should be_false
|
148
|
+
end
|
149
|
+
|
150
|
+
it "returns false if locale is not valid" do
|
151
|
+
@sucker.key = "key"
|
152
|
+
@sucker.locale = "US"
|
153
|
+
@sucker.secret = "secret"
|
154
|
+
@sucker.send(:valid?).should be_false
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
metadata
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sucker
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Hakan Ensari
|
14
|
+
- Piotr Laszewski
|
15
|
+
autorequire:
|
16
|
+
bindir: bin
|
17
|
+
cert_chain: []
|
18
|
+
|
19
|
+
date: 2010-07-21 00:00:00 +01:00
|
20
|
+
default_executable:
|
21
|
+
dependencies:
|
22
|
+
- !ruby/object:Gem::Dependency
|
23
|
+
prerelease: false
|
24
|
+
type: :runtime
|
25
|
+
name: crack
|
26
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
27
|
+
none: false
|
28
|
+
requirements:
|
29
|
+
- - "="
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
hash: 11
|
32
|
+
segments:
|
33
|
+
- 0
|
34
|
+
- 1
|
35
|
+
- 8
|
36
|
+
version: 0.1.8
|
37
|
+
requirement: *id001
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
prerelease: false
|
40
|
+
type: :runtime
|
41
|
+
name: curb
|
42
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
43
|
+
none: false
|
44
|
+
requirements:
|
45
|
+
- - "="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
hash: 105
|
48
|
+
segments:
|
49
|
+
- 0
|
50
|
+
- 7
|
51
|
+
- 7
|
52
|
+
- 1
|
53
|
+
version: 0.7.7.1
|
54
|
+
requirement: *id002
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
prerelease: false
|
57
|
+
type: :development
|
58
|
+
name: rspec
|
59
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
60
|
+
none: false
|
61
|
+
requirements:
|
62
|
+
- - "="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
hash: 62196417
|
65
|
+
segments:
|
66
|
+
- 2
|
67
|
+
- 0
|
68
|
+
- 0
|
69
|
+
- beta
|
70
|
+
- 17
|
71
|
+
version: 2.0.0.beta.17
|
72
|
+
requirement: *id003
|
73
|
+
- !ruby/object:Gem::Dependency
|
74
|
+
prerelease: false
|
75
|
+
type: :development
|
76
|
+
name: ruby-debug
|
77
|
+
version_requirements: &id004 !ruby/object:Gem::Requirement
|
78
|
+
none: false
|
79
|
+
requirements:
|
80
|
+
- - "="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
hash: 49
|
83
|
+
segments:
|
84
|
+
- 0
|
85
|
+
- 10
|
86
|
+
- 3
|
87
|
+
version: 0.10.3
|
88
|
+
requirement: *id004
|
89
|
+
description: Sucker is a thin Ruby wrapper to the Amazon Product Advertising API.
|
90
|
+
email: code@papercavalier.com
|
91
|
+
executables: []
|
92
|
+
|
93
|
+
extensions: []
|
94
|
+
|
95
|
+
extra_rdoc_files:
|
96
|
+
- LICENSE
|
97
|
+
- README.textile
|
98
|
+
files:
|
99
|
+
- LICENSE
|
100
|
+
- lib/sucker.rb
|
101
|
+
- lib/sucker/request.rb
|
102
|
+
- README.textile
|
103
|
+
- spec/integration/item_lookup_spec.rb
|
104
|
+
- spec/integration/seller_listing_search_spec.rb
|
105
|
+
- spec/spec_helper.rb
|
106
|
+
- spec/support/amazon_credentials.rb
|
107
|
+
- spec/support/curb_stubber.rb
|
108
|
+
- spec/unit/sucker/request_spec.rb
|
109
|
+
- spec/unit/sucker_spec.rb
|
110
|
+
has_rdoc: true
|
111
|
+
homepage: http://github.com/papercavalier/sucker
|
112
|
+
licenses: []
|
113
|
+
|
114
|
+
post_install_message:
|
115
|
+
rdoc_options:
|
116
|
+
- --charset=UTF-8
|
117
|
+
require_paths:
|
118
|
+
- lib
|
119
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
120
|
+
none: false
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
hash: 3
|
125
|
+
segments:
|
126
|
+
- 0
|
127
|
+
version: "0"
|
128
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ">="
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
hash: 3
|
134
|
+
segments:
|
135
|
+
- 0
|
136
|
+
version: "0"
|
137
|
+
requirements: []
|
138
|
+
|
139
|
+
rubyforge_project:
|
140
|
+
rubygems_version: 1.3.7
|
141
|
+
signing_key:
|
142
|
+
specification_version: 3
|
143
|
+
summary: A thin Ruby wrapper to the Amazon Product Advertising API
|
144
|
+
test_files:
|
145
|
+
- spec/integration/item_lookup_spec.rb
|
146
|
+
- spec/integration/seller_listing_search_spec.rb
|
147
|
+
- spec/spec_helper.rb
|
148
|
+
- spec/support/amazon_credentials.rb
|
149
|
+
- spec/support/curb_stubber.rb
|
150
|
+
- spec/unit/sucker/request_spec.rb
|
151
|
+
- spec/unit/sucker_spec.rb
|