sucker 0.7.1 → 0.8.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/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
|
-

|
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
|