vacuum 1.1.1 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5e4bd6227abb1fea07adb3e354bad09a688b86f7
4
- data.tar.gz: c422eef181619b91410a1adb2568de0622da0744
3
+ metadata.gz: 99bd9a237d04b447017964b0b8f672d95f2d06ba
4
+ data.tar.gz: 7cca17378340136b4af9d4038b26822b7e07e3e3
5
5
  SHA512:
6
- metadata.gz: a4427bfcdfff025d95dc70084afd7c9af29e5de0c5e64bae4cebf7f09634881890544dee2adcaaffb327a712dd4e331e4b56284c17db9e1dbb5ac1e89e46faa6
7
- data.tar.gz: 6b2a8f8fffdf7b003252b9014744050223c7b6835797d860b737668a9f79aac902f0fb268cf8b271fbe162eacbc5bedb204b83a83d7da90ad201b34dab60efa3
6
+ metadata.gz: d6162aca52ed85ae0ee728d0fcd7cb21269e316478fe685e401c1181793e039bf85cf72dc5099772f43deaf51965623ceb3e2fae1e31e56f9aaa0c83ff562b47
7
+ data.tar.gz: 9cab62d3c97f2a6f0d604d0d32d454ac4d58fea793b3977bdf8352746273bb20a55cb66adebe69c2575c76dc0caaa7d9c7d951f09c07fcd431b3c932c2aa9222
data/README.md CHANGED
@@ -1,96 +1,193 @@
1
1
  # Vacuum
2
+ [![Travis](https://travis-ci.org/hakanensari/vacuum.svg)](https://travis-ci.org/hakanensari/vacuum)
2
3
 
3
- [![Build Status][1]][2]
4
+ Vacuum is a fast, light-weight Ruby wrapper to the [Amazon Product Advertising API](https://affiliate-program.amazon.com/gp/advertising/api/detail/main.html).
4
5
 
5
- Vacuum is a fast, light-weight Ruby wrapper to the [Amazon Product Advertising API][4].
6
-
7
- ![vacuum][3]
6
+ ![vacuum](http://f.cl.ly/items/2k2X0e2u0G3k1c260D2u/vacuum.png)
8
7
 
9
8
  ## Usage
10
9
 
11
10
  ### Setup
12
11
 
13
- Set up a request:
12
+ Create a request:
14
13
 
15
14
  ```ruby
16
- req = Vacuum.new
15
+ request = Vacuum.new
17
16
  ```
18
17
 
19
- The locale defaults to the US. To use another locale, instantiate with its
20
- two-letter country code:
18
+ The locale will default to the US. To use another locale, reference its two-letter country code:
21
19
 
22
20
  ```ruby
23
- req = Vacuum.new('GB')
21
+ request = Vacuum.new('GB')
24
22
  ```
25
23
 
26
24
  Configure the request credentials:
27
25
 
28
26
  ```ruby
29
- req.configure(
30
- aws_access_key_id: 'key',
27
+ request.configure(
28
+ aws_access_key_id: 'key',
31
29
  aws_secret_access_key: 'secret',
32
- associate_tag: 'tag'
30
+ associate_tag: 'tag'
33
31
  )
34
32
  ```
35
33
 
36
- Alternatively, set the key and secret as environment variables globally:
34
+ You can omit the above if you set your key and secret as environment variables:
37
35
 
38
36
  ```sh
39
37
  export AWS_ACCESS_KEY_ID=key
40
38
  export AWS_SECRET_ACCESS_KEY=secret
41
39
  ```
42
40
 
43
- You will still need to set a distinct associate tag for each locale:
41
+ You will still need to set an associate tag:
44
42
 
45
43
  ```ruby
46
- req.associate_tag = 'tag'
44
+ request.associate_tag = 'tag'
47
45
  ```
48
46
 
47
+ Provided you are looking to earn commission, you have to register independently with each locale you query. Otherwise, you may reuse any dummy associate tag.
48
+
49
49
  ### Request
50
50
 
51
- Set up your parameters and make a request:
51
+ #### Browse Node Lookup
52
+
53
+ **BrowseNodeLookup** returns a specified browse node’s name and ancestors:
52
54
 
53
55
  ```ruby
54
- params = {
55
- 'SearchIndex' => 'Books',
56
- 'Keywords' => 'Architecture'
57
- }
58
- res = req.item_search(query: params)
56
+ response = request.browse_node_lookup(
57
+ query: {
58
+ 'BrowseNodeId' => 123
59
+ }
60
+ )
59
61
  ```
60
- The above executes an item search operation. The names of available methods
61
- derive from the operations listed in the API docs and include
62
- `browse_node_lookup`, `cart_add`, `cart_clear`, `cart_create`, `cart_get`,
63
- `cart_modify`, `item_lookup`, `item_search`, and `similarity_lookup`.
64
62
 
65
- Vacuum uses [Excon][5] as HTTP client. Check the Excon API for ways to tweak
66
- your request:
63
+ #### Cart Operations
64
+
65
+ The **CartCreate** operation creates a remote shopping cart:
67
66
 
68
67
  ```ruby
69
- res = req.item_search(query: params, persistent: true)
68
+ response = request.cart_create(
69
+ query: {
70
+ 'HMAC' => 'secret',
71
+ 'Item.1.OfferListingId' => '123',
72
+ 'Item.1.Quantity' => 1
73
+ }
74
+ )
70
75
  ```
71
76
 
72
- ### Response
77
+ The **CartAdd** operation adds items to an existing remote shopping cart:
78
+
79
+ ```ruby
80
+ response = request.cart_add(
81
+ query: {
82
+ 'CartId' => '123',
83
+ 'HMAC' => 'secret',
84
+ 'Item.1.OfferListingId' => '123',
85
+ 'Item.1.Quantity' => 1
86
+ }
87
+ )
88
+ ```
89
+
90
+ The **CartClear** operation removes all of the items in a remote shopping cart:
91
+
92
+ ```ruby
93
+ response = request.cart_clear(
94
+ query: {
95
+ 'CartId' => '123',
96
+ 'HMAC' => 'secret'
97
+ }
98
+ )
99
+ ```
100
+
101
+ The **CartGet** operation retrieves the IDs, quantities, and prices of the items, including SavedForLater ones, in a remote shopping cart:
102
+
103
+ ```ruby
104
+ response = request.cart_get(
105
+ query: {
106
+ 'CartId' => '123',
107
+ 'HMAC' => 'secret',
108
+ 'CartItemId' => '123'
109
+ }
110
+ )
111
+ ```
112
+
113
+ #### Item Lookup
114
+
115
+ The **ItemLookup** operation returns some or all of the attributes of an item, depending on the response group specified in the request. By default, the operation returns an item’s ASIN, manufacturer, product group, and title.
116
+
117
+ ```ruby
118
+ response = request.item_lookup(
119
+ query: {
120
+ 'ItemId' => '0679753354'
121
+ }
122
+ )
123
+ ```
73
124
 
74
- The quickest way to consume a response is to parse it into a Ruby hash:
125
+ #### Item Search
126
+
127
+ The **ItemSearch** operation returns items that satisfy the search criteria, including one or more search indices.
75
128
 
76
129
  ```ruby
77
- res.to_h
130
+ response = request.item_search(
131
+ query: {
132
+ 'Keywords' => 'Architecture',
133
+ 'SearchIndex' => 'Books'
134
+ }
135
+ )
78
136
  ```
79
137
 
80
- Vacuum uses [MultiXml][6], which will work with a number of popular XML
81
- libraries. If working in MRI, you may want to use [Ox][7].
138
+ #### Similarity Lookup
82
139
 
83
- You can also pass the response body into your own parser for some custom XML
84
- heavy-lifting:
140
+ The **SimilarityLookup** operation returns up to ten products per page that are similar to one or more items specified in the request. This operation is typically used to pique a customer’s interest in buying something similar to what they’ve already ordered.
85
141
 
86
142
  ```ruby
87
- MyParser.new(res.body)
143
+ response = request.similarity_lookup(
144
+ query: {
145
+ 'ItemId' => '0679753354'
146
+ }
147
+ )
148
+ ```
149
+
150
+ #### Configuring a request
151
+
152
+ Vacuum wraps [Excon](https://github.com/geemus/excon). Use the latter's API to tweak your request.
153
+
154
+ For example, to use a persistent connection:
155
+
156
+ ```ruby
157
+ response = request.item_search(
158
+ query: {
159
+ 'ItemId' => '0679753354'
160
+ },
161
+ persistent: true
162
+ )
163
+ ```
164
+
165
+ ### Response
166
+
167
+ The quick and dirty way to consume a response is to parse it into a Ruby hash:
168
+
169
+ ```ruby
170
+ response.to_h
171
+ ```
172
+
173
+ In production, you may prefer to use a custom parser to do some XML heavy-lifting:
174
+
175
+ ```ruby
176
+ class MyParser
177
+ # A parser has to respond to this.
178
+ def self.parse(body)
179
+ new(body)
180
+ end
181
+
182
+ def initialize(body)
183
+ @body = body
184
+ end
185
+
186
+ # Implement parser here.
187
+ end
188
+
189
+ response.parser = MyParser
190
+ response.parse
88
191
  ```
89
192
 
90
- [1]: https://secure.travis-ci.org/hakanensari/vacuum.png
91
- [2]: http://travis-ci.org/hakanensari/vacuum
92
- [3]: http://f.cl.ly/items/2k2X0e2u0G3k1c260D2u/vacuum.png
93
- [4]: https://affiliate-program.amazon.com/gp/advertising/api/detail/main.html
94
- [5]: https://github.com/geemus/excon
95
- [6]: https://github.com/sferik/multi_xml
96
- [7]: https://github.com/ohler55/ox
193
+ If no custom parser is set, `Vacuum::Response#parse` delegates to `#to_h`.
@@ -48,7 +48,7 @@ module Vacuum
48
48
  #
49
49
  # Raises a Bad Locale error if locale is not valid.
50
50
  def initialize(locale = 'US', secure = false)
51
- host = HOSTS.fetch(locale) { raise BadLocale }
51
+ host = HOSTS.fetch(locale) { fail BadLocale }
52
52
  @aws_endpoint = "#{secure ? 'https' : 'http' }://#{host}/onca/xml"
53
53
  end
54
54
 
@@ -62,7 +62,7 @@ module Vacuum
62
62
  #
63
63
  # Returns self.
64
64
  def configure(credentials)
65
- credentials.each { |key, val| self.send("#{key}=", val) }
65
+ credentials.each { |key, val| send("#{key}=", val) }
66
66
  self
67
67
  end
68
68
 
@@ -92,9 +92,9 @@ module Vacuum
92
92
  #
93
93
  # Returns a Vacuum Response.
94
94
  OPERATIONS.each do |operation|
95
- method_name = operation.gsub(/(.)([A-Z])/,'\1_\2').downcase
95
+ method_name = operation.gsub(/(.)([A-Z])/, '\1_\2').downcase
96
96
  define_method(method_name) do |params, opts = {}|
97
- params.has_key?(:query) ? opts = params : opts.update(query: params)
97
+ params.key?(:query) ? opts = params : opts.update(query: params)
98
98
  opts[:query].update('Operation' => operation)
99
99
 
100
100
  Response.new(get(opts))
@@ -2,7 +2,22 @@ require 'delegate'
2
2
  require 'multi_xml'
3
3
 
4
4
  module Vacuum
5
+ # A wrapper around the Amazon Product Advertising API response.
5
6
  class Response < SimpleDelegator
7
+ class << self
8
+ attr_accessor :parser
9
+ end
10
+
11
+ def parser
12
+ @parser || self.class.parser
13
+ end
14
+
15
+ attr_writer :parser
16
+
17
+ def parse
18
+ parser ? parser.parse(body) : to_h
19
+ end
20
+
6
21
  def to_h
7
22
  MultiXml.parse(body)
8
23
  end
@@ -1,3 +1,3 @@
1
1
  module Vacuum
2
- VERSION = '1.1.1'
2
+ VERSION = '1.2.0'
3
3
  end
@@ -18,6 +18,7 @@ class TestIntegration < Minitest::Test
18
18
  include Vacuum
19
19
 
20
20
  def setup
21
+ skip if RUBY_VERSION < '2'
21
22
  VCR.insert_cassette('vacuum')
22
23
  end
23
24
 
data/test/test_vacuum.rb CHANGED
@@ -22,23 +22,51 @@ class TestVacuum < Minitest::Test
22
22
  end
23
23
 
24
24
  def test_fetches_parsable_response
25
- Excon.stub({}, { body: '<foo>bar</foo>' })
26
- @req.configure(aws_access_key_id: 'key', aws_secret_access_key: 'secret', associate_tag: 'tag')
25
+ Excon.stub({}, body: '<foo/>')
27
26
  res = @req.item_lookup({}, mock: true)
28
- refute_empty res.to_h
27
+ refute_empty res.parse
29
28
  end
30
29
 
31
30
  def test_alternative_query_syntax
32
- Excon.stub({}, { body: '<foo>bar</foo>' })
33
- req = Request.new
34
- req.configure(aws_access_key_id: 'key', aws_secret_access_key: 'secret', associate_tag: 'tag')
35
- res = req.item_lookup(query: {}, mock: true)
36
- refute_empty res.to_h
31
+ Excon.stub({}, body: '<foo/>')
32
+ res = @req.item_lookup(query: {}, mock: true)
33
+ refute_empty res.parse
37
34
  end
38
35
 
39
36
  def test_force_encodes_body
40
37
  res = Object.new
41
- def res.body; String.new.force_encoding('ASCII-8BIT'); end
38
+ def res.body
39
+ ''.force_encoding('ASCII-8BIT')
40
+ end
42
41
  assert_equal 'UTF-8', Response.new(res).body.encoding.name
43
42
  end
43
+
44
+ def test_sets_custom_parser_on_class_level
45
+ original_parser = Response.parser
46
+ Excon.stub({}, body: '<foo/>')
47
+ parser = MiniTest::Mock.new
48
+ parser.expect(:parse, '123', ['<foo/>'])
49
+ Response.parser = parser
50
+ res = @req.item_lookup(query: {}, mock: true)
51
+ assert_equal '123', res.parse
52
+ Response.parser = original_parser # clean up
53
+ end
54
+
55
+ def test_sets_custom_parser_on_instance_level
56
+ Excon.stub({}, body: '<foo/>')
57
+ res = @req.item_lookup(query: {}, mock: true)
58
+ parser = MiniTest::Mock.new
59
+ parser.expect(:parse, '123', ['<foo/>'])
60
+ res.parser = parser
61
+ assert_equal '123', res.parse
62
+ end
63
+
64
+ def test_casts_to_hash
65
+ Excon.stub({}, body: '<foo/>')
66
+ parser = MiniTest::Mock.new
67
+ res = @req.item_lookup(query: {}, mock: true)
68
+ assert_kind_of Hash, res.to_h
69
+ res.parser = parser
70
+ assert_kind_of Hash, res.to_h
71
+ end
44
72
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vacuum
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hakan Ensari
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-04 00:00:00.000000000 Z
11
+ date: 2014-12-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jeff
@@ -96,7 +96,7 @@ dependencies:
96
96
  version: '0'
97
97
  description: A wrapper to the Amazon Product Advertising API
98
98
  email:
99
- - hakan.ensari@papercavalier.com
99
+ - me@hakanensari.com
100
100
  executables: []
101
101
  extensions: []
102
102
  extra_rdoc_files: []