sucker 0.7.1 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +30 -13
- data/lib/sucker/request.rb +2 -2
- data/lib/sucker/response.rb +3 -5
- data/lib/sucker/stub.rb +4 -0
- data/lib/sucker.rb +2 -3
- data/spec/integration/images_spec.rb +1 -2
- data/spec/integration/twenty_items_in_one_request_spec.rb +3 -0
- data/spec/spec_helper.rb +2 -5
- data/spec/unit/sucker/response_spec.rb +0 -5
- metadata +19 -24
- data/spec/benchmark/to_hash_implementations.rb +0 -38
data/README.md
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
Sucker
|
2
2
|
======
|
3
3
|
|
4
|
-
Sucker is a paper-thin Ruby wrapper to the [Amazon Product Advertising API](https://affiliate-program.amazon.co.uk/gp/advertising/api/detail/main.html). It runs on cURL and Nokogiri and supports
|
4
|
+
Sucker is a paper-thin Ruby wrapper to the [Amazon Product Advertising API](https://affiliate-program.amazon.co.uk/gp/advertising/api/detail/main.html). It runs on cURL and Nokogiri and supports __everything in the API__.
|
5
5
|
|
6
|
-
![Sucker](http://upload.wikimedia.org/wikipedia/
|
6
|
+
![Sucker](http://upload.wikimedia.org/wikipedia/commons/thumb/f/f8/FEMA_-_32011_-_FEMA_Joint_Field_Office_%28JFO%29_preparation_in_Ohio.jpg/540px-FEMA_-_32011_-_FEMA_Joint_Field_Office_%28JFO%29_preparation_in_Ohio.jpg)
|
7
7
|
|
8
8
|
Examples
|
9
9
|
--------
|
@@ -13,15 +13,17 @@ Set up a worker.
|
|
13
13
|
worker = Sucker.new(
|
14
14
|
:locale => "us",
|
15
15
|
:key => "API KEY",
|
16
|
-
:secret => "API SECRET"
|
17
|
-
:associate_tag => "ASSOCIATE TAG")
|
16
|
+
:secret => "API SECRET")
|
18
17
|
|
19
|
-
|
18
|
+
Optionally, fiddle with curl. Say you want to use multiple network interfaces to query Amazon:
|
20
19
|
|
21
20
|
worker.curl { |c| c.interface = "eth1" }
|
22
21
|
|
23
22
|
Set up a request.
|
24
23
|
|
24
|
+
asin_batch = %w{
|
25
|
+
0816614024 0143105825 0485113600 0816616779 0942299078
|
26
|
+
0816614008 144006654X 0486400360 0486417670 087220474X }
|
25
27
|
worker << {
|
26
28
|
"Operation" => "ItemLookup",
|
27
29
|
"IdType" => "ASIN",
|
@@ -39,20 +41,24 @@ View the internals of the response object.
|
|
39
41
|
response.body,
|
40
42
|
response.xml
|
41
43
|
|
42
|
-
|
44
|
+
Here is the response parsed into a simple hash:
|
43
45
|
|
44
46
|
pp response.to_hash
|
45
|
-
|
46
|
-
response.node("Item").each { |book| do_something }
|
47
|
-
response.node("Error").each { |error| do_something }
|
48
47
|
|
49
|
-
|
48
|
+
But you will probably be more interested particular nodes:
|
50
49
|
|
51
|
-
|
52
|
-
|
50
|
+
response.node("Item"),
|
51
|
+
response.node("Error")
|
52
|
+
|
53
|
+
Fetch another ASIN in a more DSL-y way.
|
54
|
+
|
55
|
+
worker << { "ItemId" => "0486454398" }
|
56
|
+
pp worker.get.node("Item")
|
53
57
|
|
54
58
|
Check the integration specs for more examples.
|
55
59
|
|
60
|
+
Ultimately, you should rely on the API documentation to build your queries.
|
61
|
+
|
56
62
|
Stubbing
|
57
63
|
--------
|
58
64
|
|
@@ -69,7 +75,18 @@ In your spec, you can now stub the worker:
|
|
69
75
|
|
70
76
|
The first time you run the spec, Sucker will perform the actual request. Following requests will use a cached response.
|
71
77
|
|
78
|
+
Active Support
|
79
|
+
--------------
|
80
|
+
Sucker::Response relies on the Nokogiri implementation of the XmlMini parser in Active Support (~> 3.0).
|
81
|
+
|
82
|
+
In a non-Rails environment, that merely means requiring twenty-something lines of code from Active Support.
|
83
|
+
|
72
84
|
Compatibility
|
73
85
|
-------------
|
74
86
|
|
75
|
-
Specs pass against Ruby 1.8.7, 1.9.
|
87
|
+
Specs pass against Ruby 1.8.7, 1.9.2, and REE.
|
88
|
+
|
89
|
+
Todo
|
90
|
+
----
|
91
|
+
|
92
|
+
* See if I can do away with the stub class and use something like VCR in its place.
|
data/lib/sucker/request.rb
CHANGED
@@ -8,8 +8,8 @@ module Sucker
|
|
8
8
|
:de => 'ecs.amazonaws.de',
|
9
9
|
:ca => 'ecs.amazonaws.ca',
|
10
10
|
:fr => 'ecs.amazonaws.fr',
|
11
|
-
:jp => 'ecs.amazonaws.jp' }
|
12
|
-
PATH = "/onca/xml"
|
11
|
+
:jp => 'ecs.amazonaws.jp' }.freeze
|
12
|
+
PATH = "/onca/xml".freeze
|
13
13
|
|
14
14
|
# The Amazon locale to query
|
15
15
|
attr_accessor :locale
|
data/lib/sucker/response.rb
CHANGED
@@ -2,7 +2,7 @@ module Sucker
|
|
2
2
|
|
3
3
|
# A Nokogiri-driven wrapper around the cURL response
|
4
4
|
class Response
|
5
|
-
attr_accessor :body, :code, :time
|
5
|
+
attr_accessor :body, :code, :time
|
6
6
|
|
7
7
|
def initialize(curl)
|
8
8
|
self.body = curl.body_str
|
@@ -10,18 +10,16 @@ module Sucker
|
|
10
10
|
self.time = curl.total_time
|
11
11
|
end
|
12
12
|
|
13
|
-
# Queries an xpath and returns
|
13
|
+
# Queries an xpath and returns result as an array of hashes
|
14
14
|
def node(path)
|
15
15
|
xml.xpath("//xmlns:#{path}").map { |node| strip_content(node.to_hash[path]) }
|
16
16
|
end
|
17
17
|
|
18
|
-
#
|
18
|
+
# Parses the response into a simple hash
|
19
19
|
def to_hash
|
20
20
|
strip_content(xml.to_hash)
|
21
21
|
end
|
22
22
|
|
23
|
-
alias :to_h :to_hash
|
24
|
-
|
25
23
|
# The XML document
|
26
24
|
def xml
|
27
25
|
@xml ||= Nokogiri::XML(body)
|
data/lib/sucker/stub.rb
CHANGED
@@ -1,4 +1,8 @@
|
|
1
1
|
module Sucker
|
2
|
+
|
3
|
+
# Stubs Sucker::Response to run specs offline. Ideally, I'd like to use
|
4
|
+
# a general-purpose stubber for Curb but last time I checked, there was
|
5
|
+
# none.
|
2
6
|
class MockResponse < Response
|
3
7
|
def initialize(mock_response_body)
|
4
8
|
self.body = mock_response_body
|
data/lib/sucker.rb
CHANGED
@@ -8,10 +8,9 @@ require "sucker/response"
|
|
8
8
|
# = Sucker
|
9
9
|
# Sucker is a paper-thin Ruby wrapper to the Amazon Product Advertising API.
|
10
10
|
module Sucker
|
11
|
-
|
12
|
-
|
13
|
-
AMAZON_API_VERSION = "2010-06-01"
|
11
|
+
AMAZON_API_VERSION = "2010-06-01".freeze
|
14
12
|
|
13
|
+
# Instantiates a new Sucker::Request
|
15
14
|
def self.new(args={})
|
16
15
|
Sucker::Request.new(args)
|
17
16
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -59,11 +59,6 @@ module Sucker
|
|
59
59
|
@response.to_hash["book"]["title"].should be_an_instance_of String
|
60
60
|
end
|
61
61
|
|
62
|
-
it "is aliased as to_h" do
|
63
|
-
@response.should respond_to :to_h
|
64
|
-
@response.to_h.should eql @response.to_hash
|
65
|
-
end
|
66
|
-
|
67
62
|
it "renders French" do
|
68
63
|
@response.body = "<Title>L'archéologie du savoir</Title>"
|
69
64
|
@response.to_hash["Title"].should eql "L'archéologie du savoir"
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sucker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 63
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 8
|
9
|
+
- 0
|
10
|
+
version: 0.8.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Hakan Ensari
|
@@ -16,59 +16,56 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2010-
|
19
|
+
date: 2010-09-02 00:00:00 +03:00
|
20
20
|
default_executable:
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
23
|
-
prerelease: false
|
24
23
|
type: :runtime
|
24
|
+
prerelease: false
|
25
25
|
name: activesupport
|
26
26
|
version_requirements: &id001 !ruby/object:Gem::Requirement
|
27
27
|
none: false
|
28
28
|
requirements:
|
29
|
-
- -
|
29
|
+
- - ~>
|
30
30
|
- !ruby/object:Gem::Version
|
31
|
-
hash:
|
31
|
+
hash: 7
|
32
32
|
segments:
|
33
33
|
- 3
|
34
34
|
- 0
|
35
35
|
- 0
|
36
|
-
|
37
|
-
version: 3.0.0.rc
|
36
|
+
version: 3.0.0
|
38
37
|
requirement: *id001
|
39
38
|
- !ruby/object:Gem::Dependency
|
40
|
-
prerelease: false
|
41
39
|
type: :runtime
|
40
|
+
prerelease: false
|
42
41
|
name: nokogiri
|
43
42
|
version_requirements: &id002 !ruby/object:Gem::Requirement
|
44
43
|
none: false
|
45
44
|
requirements:
|
46
|
-
- -
|
45
|
+
- - ~>
|
47
46
|
- !ruby/object:Gem::Version
|
48
|
-
hash:
|
47
|
+
hash: 7
|
49
48
|
segments:
|
50
49
|
- 1
|
51
50
|
- 4
|
52
|
-
-
|
53
|
-
|
54
|
-
version: 1.4.3.1
|
51
|
+
- 0
|
52
|
+
version: 1.4.0
|
55
53
|
requirement: *id002
|
56
54
|
- !ruby/object:Gem::Dependency
|
57
|
-
prerelease: false
|
58
55
|
type: :runtime
|
56
|
+
prerelease: false
|
59
57
|
name: curb
|
60
58
|
version_requirements: &id003 !ruby/object:Gem::Requirement
|
61
59
|
none: false
|
62
60
|
requirements:
|
63
|
-
- -
|
61
|
+
- - ~>
|
64
62
|
- !ruby/object:Gem::Version
|
65
|
-
hash:
|
63
|
+
hash: 3
|
66
64
|
segments:
|
67
65
|
- 0
|
68
66
|
- 7
|
69
|
-
-
|
70
|
-
|
71
|
-
version: 0.7.7.1
|
67
|
+
- 0
|
68
|
+
version: 0.7.0
|
72
69
|
requirement: *id003
|
73
70
|
description: A paper-thin Ruby wrapper to the Amazon Product Advertising API
|
74
71
|
email: code@papercavalier.com
|
@@ -86,7 +83,6 @@ files:
|
|
86
83
|
- lib/sucker/response.rb
|
87
84
|
- lib/sucker/stub.rb
|
88
85
|
- README.md
|
89
|
-
- spec/benchmark/to_hash_implementations.rb
|
90
86
|
- spec/integration/errors_spec.rb
|
91
87
|
- spec/integration/france_spec.rb
|
92
88
|
- spec/integration/images_spec.rb
|
@@ -136,7 +132,6 @@ signing_key:
|
|
136
132
|
specification_version: 3
|
137
133
|
summary: A paper-thin Ruby wrapper to the Amazon Product Advertising API
|
138
134
|
test_files:
|
139
|
-
- spec/benchmark/to_hash_implementations.rb
|
140
135
|
- spec/integration/errors_spec.rb
|
141
136
|
- spec/integration/france_spec.rb
|
142
137
|
- spec/integration/images_spec.rb
|
@@ -1,38 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + "/../spec_helper"
|
2
|
-
|
3
|
-
require "benchmark"
|
4
|
-
require "crack/xml"
|
5
|
-
require "xmlsimple"
|
6
|
-
|
7
|
-
worker = Sucker.new(
|
8
|
-
:locale => "us",
|
9
|
-
:key => amazon["key"],
|
10
|
-
:secret => amazon["secret"])
|
11
|
-
|
12
|
-
# Prep worker
|
13
|
-
worker << {
|
14
|
-
"Operation" => "ItemLookup",
|
15
|
-
"ItemLookup.Shared.IdType" => "ASIN",
|
16
|
-
"ItemLookup.Shared.Condition" => "All",
|
17
|
-
"ItemLookup.Shared.MerchantId" => "All",
|
18
|
-
"ItemLookup.Shared.ResponseGroup" => "OfferFull" }
|
19
|
-
|
20
|
-
# Push twenty ASINs to worker
|
21
|
-
asins = %w{
|
22
|
-
0816614024 0143105825 0485113600 0816616779 0942299078
|
23
|
-
0816614008 144006654X 0486400360 0486417670 087220474X
|
24
|
-
0486454398 0268018359 1604246014 184467598X 0312427182
|
25
|
-
1844674282 0745640974 0745646441 0826489540 1844672972 }
|
26
|
-
worker << {
|
27
|
-
"ItemLookup.1.ItemId" => asins[0, 10],
|
28
|
-
"ItemLookup.2.ItemId" => asins[10, 10] }
|
29
|
-
|
30
|
-
Sucker.stub(worker)
|
31
|
-
|
32
|
-
response = worker.get
|
33
|
-
|
34
|
-
Benchmark.bm(100) do |x|
|
35
|
-
x.report("Crack") { Crack::XML.parse(response.body) }
|
36
|
-
x.report("SimpleXml") { XmlSimple.xml_in(response.body, { "ForceArray" => false }) }
|
37
|
-
x.report("AS + Nokogiri") { response.to_hash }
|
38
|
-
end
|