sucker 1.0.0.beta.2 → 1.0.0.beta.3
Sign up to get free protection for your applications and to get access to all the features.
- data/History.md +14 -0
- data/LICENSE +2 -2
- data/README.md +66 -0
- data/lib/sucker/request.rb +10 -2
- data/lib/sucker/response.rb +13 -6
- data/lib/sucker/version.rb +1 -1
- data/spec/integration/alternate_versions_spec.rb +27 -0
- data/spec/integration/errors_spec.rb +2 -2
- data/spec/integration/france_spec.rb +1 -1
- data/spec/integration/images_spec.rb +1 -1
- data/spec/integration/item_lookup_spec.rb +4 -4
- data/spec/integration/item_search_spec.rb +1 -1
- data/spec/integration/japan_spec.rb +1 -1
- data/spec/integration/keyword_search_spec.rb +28 -0
- data/spec/integration/multiple_locales_spec.rb +3 -6
- data/spec/integration/power_search_spec.rb +36 -0
- data/spec/integration/related_items_spec.rb +3 -3
- data/spec/integration/seller_listing_search_spec.rb +1 -1
- data/spec/integration/twenty_items_spec.rb +1 -1
- data/spec/unit/sucker/response_spec.rb +13 -4
- metadata +12 -5
- data/README.markdown +0 -69
data/History.md
ADDED
data/LICENSE
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
(The MIT License)
|
2
2
|
|
3
|
-
Copyright (c)
|
3
|
+
Copyright (c) 2010 Paper Cavalier
|
4
4
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining
|
6
6
|
a copy of this software and associated documentation files (the
|
@@ -19,4 +19,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
19
19
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
20
20
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
21
21
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
22
|
-
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
Sucker
|
2
|
+
======
|
3
|
+
|
4
|
+
Sucker is a Ruby wrapper to the [Amazon Product Advertising API](https://affiliate-program.amazon.co.uk/gp/advertising/api/detail/main.html). It runs on [curb](http://github.com/taf2/curb) and [the Nokogiri implementation of the XML Mini module](http://github.com/rails/rails/blob/master/activesupport/lib/active_support/xml_mini/nokogiri.rb) in Active Support. It's fast and supports __the entire API__.
|
5
|
+
|
6
|
+
![Sucker](http://upload.wikimedia.org/wikipedia/commons/thumb/f/f8/FEMA_-_32011_-_FEMA_Joint_Field_Office_%28JFO%29_preparation_in_Ohio.jpg/480px-FEMA_-_32011_-_FEMA_Joint_Field_Office_%28JFO%29_preparation_in_Ohio.jpg)
|
7
|
+
|
8
|
+
Examples
|
9
|
+
--------
|
10
|
+
|
11
|
+
Set up a worker.
|
12
|
+
|
13
|
+
worker = Sucker.new(
|
14
|
+
:locale => "us",
|
15
|
+
:key => "API KEY",
|
16
|
+
:secret => "API SECRET")
|
17
|
+
|
18
|
+
Prepare a request.
|
19
|
+
|
20
|
+
asin_batch = %w{
|
21
|
+
0816614024 0143105825 0485113600 0816616779 0942299078
|
22
|
+
0816614008 144006654X 0486400360 0486417670 087220474X }
|
23
|
+
worker << {
|
24
|
+
"Operation" => "ItemLookup",
|
25
|
+
"IdType" => "ASIN",
|
26
|
+
"ItemId" => asin_batch,
|
27
|
+
"ResponseGroup" => ["ItemAttributes", "OfferFull"] }
|
28
|
+
|
29
|
+
Perform the request.
|
30
|
+
|
31
|
+
response = worker.get
|
32
|
+
|
33
|
+
Debug.
|
34
|
+
|
35
|
+
p response.valid?,
|
36
|
+
response.code,
|
37
|
+
response.time,
|
38
|
+
response.body,
|
39
|
+
response.xml,
|
40
|
+
response.to_hash
|
41
|
+
|
42
|
+
Iterate over items in your item lookup.
|
43
|
+
|
44
|
+
response.find("Item") { |item| ... }
|
45
|
+
|
46
|
+
Iterate over errors.
|
47
|
+
|
48
|
+
response.find("Error") { |error| ... }
|
49
|
+
|
50
|
+
Repeat ad infinitum.
|
51
|
+
|
52
|
+
Check my [integration specs](http://github.com/papercavalier/sucker/tree/master/spec/integration/) for more examples. See [twenty items](http://github.com/papercavalier/sucker/tree/master/spec/integration/twenty_items_spec.rb) and [multiple locales](http://github.com/papercavalier/sucker/tree/master/spec/integration/multiple_locales_spec.rb) for relatively advanced usage.
|
53
|
+
|
54
|
+
Last but not least, dive into the [API docs](https://affiliate-program.amazon.co.uk/gp/advertising/api/detail/main.html) to construct your own queries.
|
55
|
+
|
56
|
+
Stubbing
|
57
|
+
--------
|
58
|
+
|
59
|
+
Use [VCR](http://github.com/myronmarston/vcr) to stub your requests.
|
60
|
+
|
61
|
+
Caveat: Match URIs on host only and create a new cassette for each stubbed query. [This is how I do it](http://github.com/papercavalier/sucker/blob/master/spec/support/vcr.rb).
|
62
|
+
|
63
|
+
Compatibility
|
64
|
+
-------------
|
65
|
+
|
66
|
+
Specs pass against Ruby 1.8.7, Ruby 1.9.2, and Rubinius 1.1.
|
data/lib/sucker/request.rb
CHANGED
@@ -37,6 +37,14 @@ module Sucker #:nodoc
|
|
37
37
|
end
|
38
38
|
|
39
39
|
# A helper method that merges a hash into existing parameters
|
40
|
+
#
|
41
|
+
# worker = Sucker.new
|
42
|
+
# worker << {
|
43
|
+
# "Operation" => "ItemLookup",
|
44
|
+
# "IdType" => "ASIN",
|
45
|
+
# "ItemId" => "0816614024",
|
46
|
+
# "ResponseGroup" => "ItemAttributes" }
|
47
|
+
#
|
40
48
|
def <<(hash)
|
41
49
|
self.parameters.merge!(hash)
|
42
50
|
end
|
@@ -82,10 +90,10 @@ module Sucker #:nodoc
|
|
82
90
|
parameters["AWSAccessKeyId"] = token
|
83
91
|
end
|
84
92
|
|
85
|
-
# Sets Amazon API version
|
93
|
+
# Sets the Amazon API version
|
86
94
|
#
|
87
95
|
# worker = Sucker.new
|
88
|
-
# worker.version = '
|
96
|
+
# worker.version = '2010-06-01'
|
89
97
|
#
|
90
98
|
def version=(version)
|
91
99
|
self.parameters["Version"] = version
|
data/lib/sucker/response.rb
CHANGED
@@ -18,15 +18,22 @@ module Sucker #:nodoc
|
|
18
18
|
self.time = curl.total_time
|
19
19
|
end
|
20
20
|
|
21
|
-
# Queries an xpath and returns
|
21
|
+
# Queries an xpath and returns an array of matching nodes
|
22
22
|
#
|
23
|
-
#
|
23
|
+
# Will yield each match if a block is given
|
24
24
|
#
|
25
25
|
# response = worker.get
|
26
|
-
# response.
|
26
|
+
# response.find("Item") { |item| ... }
|
27
27
|
#
|
28
|
-
def
|
29
|
-
xml.xpath("//xmlns:#{path}").map { |node| strip_content(node.to_hash[path]) }
|
28
|
+
def find(path)
|
29
|
+
node = xml.xpath("//xmlns:#{path}").map { |node| strip_content(node.to_hash[path]) }
|
30
|
+
node.each { |e| yield e } if block_given?
|
31
|
+
node
|
32
|
+
end
|
33
|
+
|
34
|
+
def node(path) # :nodoc:
|
35
|
+
warn "[DEPRECATION] `node` is deprecated. Use `find` instead."
|
36
|
+
find(path)
|
30
37
|
end
|
31
38
|
|
32
39
|
# Parses the response into a simple hash
|
@@ -58,7 +65,7 @@ module Sucker #:nodoc
|
|
58
65
|
|
59
66
|
private
|
60
67
|
|
61
|
-
# Let's massage
|
68
|
+
# Let's massage that hash
|
62
69
|
def strip_content(node)
|
63
70
|
case node
|
64
71
|
when Array
|
data/lib/sucker/version.rb
CHANGED
@@ -0,0 +1,27 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module Sucker
|
4
|
+
describe "Alternate versions" do
|
5
|
+
use_vcr_cassette "integration/alternate_versions", :record => :new_episodes
|
6
|
+
|
7
|
+
let(:worker) do
|
8
|
+
worker = Sucker.new(
|
9
|
+
:locale => "uk",
|
10
|
+
:key => amazon["key"],
|
11
|
+
:secret => amazon["secret"])
|
12
|
+
worker << {
|
13
|
+
"Operation" => "ItemLookup",
|
14
|
+
"IdType" => "ASIN",
|
15
|
+
"ResponseGroup" => "AlternateVersions",
|
16
|
+
"ItemId" => "0141044012" }
|
17
|
+
worker
|
18
|
+
end
|
19
|
+
|
20
|
+
it "returns alternate versions" do
|
21
|
+
response = worker.get
|
22
|
+
alternate_versions = response.find("AlternateVersion")
|
23
|
+
alternate_versions.should be_an_instance_of Array
|
24
|
+
alternate_versions.first.should have_key "ASIN"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -23,13 +23,13 @@ module Sucker
|
|
23
23
|
end
|
24
24
|
|
25
25
|
it "returns two errors" do
|
26
|
-
errors = response.
|
26
|
+
errors = response.find("Error")
|
27
27
|
errors.size.should eql 2
|
28
28
|
errors.first["Message"].should include "not a valid value"
|
29
29
|
end
|
30
30
|
|
31
31
|
it "returns one item" do
|
32
|
-
items = response.
|
32
|
+
items = response.find("ItemAttributes")
|
33
33
|
items.size.should eql 1
|
34
34
|
end
|
35
35
|
end
|
@@ -25,7 +25,7 @@ module Sucker
|
|
25
25
|
worker.get
|
26
26
|
end
|
27
27
|
|
28
|
-
let(:item) { response.
|
28
|
+
let(:item) { response.find("Item").first }
|
29
29
|
|
30
30
|
it "returns an item" do
|
31
31
|
item.should be_an_instance_of Hash
|
@@ -41,8 +41,8 @@ module Sucker
|
|
41
41
|
end
|
42
42
|
|
43
43
|
it "returns no errors" do
|
44
|
-
response.
|
45
|
-
response.
|
44
|
+
response.find("Error").should be_empty
|
45
|
+
response.find("Error").should be_an_instance_of Array
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
@@ -51,7 +51,7 @@ module Sucker
|
|
51
51
|
|
52
52
|
let(:items) do
|
53
53
|
worker << { "ItemId" => ["0816614024", "0143105825"] }
|
54
|
-
worker.get.
|
54
|
+
worker.get.find("Item")
|
55
55
|
end
|
56
56
|
|
57
57
|
it "returns two items" do
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module Sucker
|
4
|
+
describe "Keyword Search" do
|
5
|
+
use_vcr_cassette "integration/keyword_search", :record => :new_episodes
|
6
|
+
|
7
|
+
let(:worker) do
|
8
|
+
worker = Sucker.new(
|
9
|
+
:locale => "us",
|
10
|
+
:key => amazon["key"],
|
11
|
+
:secret => amazon["secret"])
|
12
|
+
worker << {
|
13
|
+
"Operation" => "ItemSearch",
|
14
|
+
"SearchIndex" => "Books",
|
15
|
+
"Keywords" => "zizek lacan",
|
16
|
+
"Sort" => "relevancerank" } # also try salesrank and reviewrank
|
17
|
+
worker
|
18
|
+
end
|
19
|
+
|
20
|
+
it "returns matches" do
|
21
|
+
items = worker.get.find("Item")
|
22
|
+
items.size.should > 0
|
23
|
+
items.each do |item|
|
24
|
+
item["ItemAttributes"]["Title"].should_not be_nil
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -11,8 +11,6 @@ module Sucker
|
|
11
11
|
params = {
|
12
12
|
"Operation" => "ItemLookup",
|
13
13
|
"IdType" => "ASIN",
|
14
|
-
"Condition" => "All",
|
15
|
-
"MerchantId" => "All",
|
16
14
|
"ResponseGroup" => "ItemAttributes",
|
17
15
|
"ItemId" => "0816614024" }
|
18
16
|
|
@@ -27,11 +25,10 @@ module Sucker
|
|
27
25
|
end
|
28
26
|
end
|
29
27
|
|
30
|
-
bindings =
|
31
|
-
threads.each do |thread|
|
28
|
+
bindings = threads.map do |thread|
|
32
29
|
thread.join
|
33
|
-
item = thread[:response].
|
34
|
-
|
30
|
+
item = thread[:response].find("Item").first
|
31
|
+
item["ItemAttributes"]["Binding"]
|
35
32
|
end
|
36
33
|
|
37
34
|
bindings.uniq.should =~ %w{ Paperback Taschenbuch Broché ペーパーバック }
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
# http://docs.amazonwebservices.com/AWSECommerceService/2010-09-01/DG/index.html?PowerSearchSyntax.html
|
4
|
+
#
|
5
|
+
# author: ambrose and binding: (abridged or large print) and pubdate: after 11-1996
|
6
|
+
# subject: history and (Spain or Mexico) and not military and language: Spanish
|
7
|
+
# (subject: marketing and author: kotler) or (publisher: harper and subject: "high technology")
|
8
|
+
# keywords: "high tech*" and not fiction and pubdate: during 1999
|
9
|
+
# isbn: 0446394319 or 0306806819 or 1567993850
|
10
|
+
|
11
|
+
module Sucker
|
12
|
+
describe "Power search" do
|
13
|
+
use_vcr_cassette "integration/power_search", :record => :new_episodes
|
14
|
+
|
15
|
+
let(:worker) do
|
16
|
+
worker = Sucker.new(
|
17
|
+
:locale => "us",
|
18
|
+
:key => amazon["key"],
|
19
|
+
:secret => amazon["secret"])
|
20
|
+
worker << {
|
21
|
+
"Operation" => "ItemSearch",
|
22
|
+
"SearchIndex" => "Books",
|
23
|
+
"Power" => "author:lacan or deleuze and not fiction",
|
24
|
+
"Sort" => "relevancerank" }
|
25
|
+
worker
|
26
|
+
end
|
27
|
+
|
28
|
+
it "returns matches" do
|
29
|
+
items = worker.get.find("Item")
|
30
|
+
items.size.should > 0
|
31
|
+
items.each do |item|
|
32
|
+
item["ItemAttributes"]["Title"].should_not be_nil
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -23,8 +23,8 @@ module Sucker
|
|
23
23
|
it "finds parent and related items" do
|
24
24
|
worker << { "ItemId" => "0415246334" }
|
25
25
|
response = worker.get
|
26
|
-
response.
|
27
|
-
parent_asin = response.
|
26
|
+
response.find("RelatedItem").size.should eql 1
|
27
|
+
parent_asin = response.find("RelatedItem").first["Item"]["ASIN"]
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
@@ -34,7 +34,7 @@ module Sucker
|
|
34
34
|
it "finds related items" do
|
35
35
|
worker << { "ItemId" => "B000ASPUES" }
|
36
36
|
response = worker.get
|
37
|
-
response.
|
37
|
+
response.find("RelatedItem").size.should > 1
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
@@ -40,16 +40,25 @@ module Sucker
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
-
context "#
|
44
|
-
it "returns
|
45
|
-
node = response.
|
43
|
+
context "#find" do
|
44
|
+
it "returns an array of matching nodes" do
|
45
|
+
node = response.find("ItemAttributes")
|
46
46
|
node.map { |book| book["ISBN"] }.should eql asins
|
47
47
|
end
|
48
48
|
|
49
49
|
it "returns an empty array if there are no matches" do
|
50
|
-
node = response.
|
50
|
+
node = response.find("Foo")
|
51
51
|
node.should eql []
|
52
52
|
end
|
53
|
+
|
54
|
+
it "yields to a block if given one" do
|
55
|
+
has_yielded = false
|
56
|
+
response.find("ItemAttributes") do |item|
|
57
|
+
has_yielded = true
|
58
|
+
item.should be_an_instance_of Hash
|
59
|
+
end
|
60
|
+
has_yielded.should be_true
|
61
|
+
end
|
53
62
|
end
|
54
63
|
|
55
64
|
context "#to_hash" do
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sucker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 62196357
|
5
5
|
prerelease: true
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 0
|
9
9
|
- 0
|
10
10
|
- beta
|
11
|
-
-
|
12
|
-
version: 1.0.0.beta.
|
11
|
+
- 3
|
12
|
+
version: 1.0.0.beta.3
|
13
13
|
platform: ruby
|
14
14
|
authors:
|
15
15
|
- Hakan Ensari
|
@@ -18,7 +18,7 @@ autorequire:
|
|
18
18
|
bindir: bin
|
19
19
|
cert_chain: []
|
20
20
|
|
21
|
-
date: 2010-10-
|
21
|
+
date: 2010-10-25 00:00:00 +01:00
|
22
22
|
default_executable:
|
23
23
|
dependencies:
|
24
24
|
- !ruby/object:Gem::Dependency
|
@@ -196,15 +196,19 @@ files:
|
|
196
196
|
- lib/sucker/version.rb
|
197
197
|
- lib/sucker.rb
|
198
198
|
- LICENSE
|
199
|
-
- README.
|
199
|
+
- README.md
|
200
|
+
- History.md
|
200
201
|
- spec/fixtures/asins.txt
|
202
|
+
- spec/integration/alternate_versions_spec.rb
|
201
203
|
- spec/integration/errors_spec.rb
|
202
204
|
- spec/integration/france_spec.rb
|
203
205
|
- spec/integration/images_spec.rb
|
204
206
|
- spec/integration/item_lookup_spec.rb
|
205
207
|
- spec/integration/item_search_spec.rb
|
206
208
|
- spec/integration/japan_spec.rb
|
209
|
+
- spec/integration/keyword_search_spec.rb
|
207
210
|
- spec/integration/multiple_locales_spec.rb
|
211
|
+
- spec/integration/power_search_spec.rb
|
208
212
|
- spec/integration/related_items_spec.rb
|
209
213
|
- spec/integration/seller_listing_search_spec.rb
|
210
214
|
- spec/integration/twenty_items_spec.rb
|
@@ -254,13 +258,16 @@ specification_version: 3
|
|
254
258
|
summary: A Ruby wrapper to the Amazon Product Advertising API
|
255
259
|
test_files:
|
256
260
|
- spec/fixtures/asins.txt
|
261
|
+
- spec/integration/alternate_versions_spec.rb
|
257
262
|
- spec/integration/errors_spec.rb
|
258
263
|
- spec/integration/france_spec.rb
|
259
264
|
- spec/integration/images_spec.rb
|
260
265
|
- spec/integration/item_lookup_spec.rb
|
261
266
|
- spec/integration/item_search_spec.rb
|
262
267
|
- spec/integration/japan_spec.rb
|
268
|
+
- spec/integration/keyword_search_spec.rb
|
263
269
|
- spec/integration/multiple_locales_spec.rb
|
270
|
+
- spec/integration/power_search_spec.rb
|
264
271
|
- spec/integration/related_items_spec.rb
|
265
272
|
- spec/integration/seller_listing_search_spec.rb
|
266
273
|
- spec/integration/twenty_items_spec.rb
|
data/README.markdown
DELETED
@@ -1,69 +0,0 @@
|
|
1
|
-
Sucker
|
2
|
-
======
|
3
|
-
|
4
|
-
Sucker is a Ruby wrapper to the [Amazon Product Advertising API](https://affiliate-program.amazon.co.uk/gp/advertising/api/detail/main.html). It runs on [curb](http://github.com/taf2/curb) and the Nokogiri implementation of the XML Mini module in Active Support. It is blazing fast and supports __the entire API__.
|
5
|
-
|
6
|
-
![Sucker](http://upload.wikimedia.org/wikipedia/commons/thumb/f/f8/FEMA_-_32011_-_FEMA_Joint_Field_Office_%28JFO%29_preparation_in_Ohio.jpg/480px-FEMA_-_32011_-_FEMA_Joint_Field_Office_%28JFO%29_preparation_in_Ohio.jpg)
|
7
|
-
|
8
|
-
Examples
|
9
|
-
--------
|
10
|
-
|
11
|
-
Set up a worker.
|
12
|
-
|
13
|
-
worker = Sucker.new(
|
14
|
-
:locale => "us",
|
15
|
-
:key => "API KEY",
|
16
|
-
:secret => "API SECRET")
|
17
|
-
|
18
|
-
Prep a request.
|
19
|
-
|
20
|
-
asin_batch = %w{
|
21
|
-
0816614024 0143105825 0485113600 0816616779 0942299078
|
22
|
-
0816614008 144006654X 0486400360 0486417670 087220474X }
|
23
|
-
worker << {
|
24
|
-
"Operation" => "ItemLookup",
|
25
|
-
"IdType" => "ASIN",
|
26
|
-
"ItemId" => asin_batch,
|
27
|
-
"ResponseGroup" => ["ItemAttributes", "OfferFull"] }
|
28
|
-
|
29
|
-
Perform the request.
|
30
|
-
|
31
|
-
response = worker.get
|
32
|
-
|
33
|
-
Debug.
|
34
|
-
|
35
|
-
if response.valid?
|
36
|
-
p response.code,
|
37
|
-
response.time,
|
38
|
-
response.body,
|
39
|
-
response.xml,
|
40
|
-
response.to_hash
|
41
|
-
end
|
42
|
-
|
43
|
-
Say you performed an item lookup. Iterate over all items and errors.
|
44
|
-
|
45
|
-
response.node("Item").each { |item| ... }
|
46
|
-
response.node("Error").each { |error| ... }
|
47
|
-
|
48
|
-
Perform a new request in a more DSL-y way.
|
49
|
-
|
50
|
-
worker << { "ItemId" => "0486454398" }
|
51
|
-
worker.get.node("Item").each { |item| ... }
|
52
|
-
|
53
|
-
Repeat ad infinitum.
|
54
|
-
|
55
|
-
Check the [integration specs](http://github.com/papercavalier/sucker/tree/master/spec/integration/) for more examples. In particullar, see [twenty items](http://github.com/papercavalier/sucker/tree/master/spec/integration/twenty_items_spec.rb) and [multiple locales](http://github.com/papercavalier/sucker/tree/master/spec/integration/multiple_locales_spec.rb) for advanced usage.
|
56
|
-
|
57
|
-
Finally, dive into the [API docs](https://affiliate-program.amazon.co.uk/gp/advertising/api/detail/main.html) to construct your own queries.
|
58
|
-
|
59
|
-
Stubbing
|
60
|
-
--------
|
61
|
-
|
62
|
-
Use [VCR](http://github.com/myronmarston/vcr) to stub your requests. [This file](http://github.com/papercavalier/sucker/blob/master/spec/support/vcr.rb) should help you set up VCR with RSpec.
|
63
|
-
|
64
|
-
Don't match requests on URI. The parameters include a timestamp that results in each URI being unique.
|
65
|
-
|
66
|
-
Compatibility
|
67
|
-
-------------
|
68
|
-
|
69
|
-
Specs pass against Ruby 1.8.7, Ruby 1.9.2, and Rubinius 1.1.
|