ruby-mws 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -4,4 +4,5 @@ Gemfile.lock
4
4
  pkg/*
5
5
  .DS_Store
6
6
  spec/credentials.yml
7
- spec/fixtures/ephemeral_response/*
7
+ spec/fixtures/ephemeral_response/*
8
+ .rvmrc
data/README.markdown CHANGED
@@ -1,41 +1,48 @@
1
1
  ruby-mws
2
2
  ========
3
3
 
4
- Under development
5
- -----------------
4
+ by Erik Lyngved
6
5
 
7
- This is a Ruby gem that wraps the Amazon Marketplace Web Service (MWS) API. It is still missing many features, but some basic requests are available.
6
+ ### Read me!
8
7
 
9
- Please use at your own risk. This has not been tested thoroughly and is not guaranteed to work in any capacity. See the LICENSE file for more details.
8
+ ruby-mws is a Ruby gem that wraps the Amazon Marketplace Web Service (MWS) API. Right now it only supports Amazon's Order and Inventory APIs.
9
+
10
+ I made this gem for my own purposes, and it's not fully featured. Pull requests or bug reports are always welcome.
10
11
 
11
12
  Quick Start
12
13
  -----------
13
14
 
14
- ### Initialize the connection object
15
+ To quickly test your connection to the service without credentials, you can ping the server, which returns server time in UTC:
16
+
17
+ MWS::Base.server_time
18
+
19
+ ### Initialization
15
20
 
16
21
  Pass in your developer account credentials. All four params below are required.
17
22
 
18
- mws = MWS.new {:aws_access_key_id => "AKIAIFKEXAMPLE4WZHHA",
23
+ mws = MWS.new (:aws_access_key_id => "AKIAIFKEXAMPLE4WZHHA",
19
24
  :secret_access_key => "abc123def456/SECRET/+ghi789jkl",
20
25
  :seller_id => "A27WEXAMPLEBXY",
21
- :marketplace_id => "ATVPDKIKX0DER"}
26
+ :marketplace_id => "ATVPDKIKX0DER")
22
27
 
23
- ### Make a request
28
+ ### Requests
24
29
 
25
- Let's use the Orders API to retrieve recently updated orders.
30
+ We'll use the Orders API to retrieve recently updated orders.
26
31
 
27
32
  # Retrieve all orders updated within the last 4 hours
28
- response = mws.orders.list_orders :last_updated_after => Time.now-4.hours # Rails helper used
33
+ response = mws.orders.list_orders :last_updated_after => 4.hours.ago # ActiveSupport time helper
29
34
 
30
35
  (All datetime fields accept Time or DateTime objects, as well as strings in iso8601 format.)
31
36
 
32
- ### Parse the response
37
+ ### Responses
33
38
 
34
- We can parse our response to view the orders and any other data returned.
39
+ Response objects inherit [Hashie](http://github.com/intridea/hashie) for easy access and [Rash](http://github.com/tcocca/rash) to convert Amazon's CamelCase convention to underscore. So you're just left with plain ol' Ruby goodness.
40
+
41
+ Let's parse our response to view the orders and any other data returned.
35
42
 
36
43
  response.orders.first # => { "amazon_order_id" => "002-EXAMPLE-0031387",
37
- "purchase_date" => "2012-01-13T19:11:46.000Z",
38
- ... }
44
+ # "purchase_date" => "2012-01-13T19:11:46.000Z",
45
+ # ... }
39
46
 
40
47
  Response objects are accessible in Hash or method notation.
41
48
 
@@ -50,35 +57,31 @@ Use `keys` and `has_key?` to discover what's in the response.
50
57
 
51
58
  For responses with long lists of data, results are returned from the service in pages (usually 100 per page). Example:
52
59
 
53
- response = mws.orders.list_orders :last_updated_after => Time.now-1.week # returns 100 orders
60
+ response = mws.orders.list_orders :last_updated_after => 1.week.ago # returns 100 orders & next_token
54
61
 
55
62
  Here, there are more orders to be returned. You can call `has_next?` on the same API instance to see if the last response returned has a next page. If so, calling `next` will make the request for the next page.
56
63
 
57
64
  mws.orders.has_next? # => true
58
65
  next_response = mws.orders.next # returns next page of orders
59
66
 
60
- You can keep calling `next` on the API instance as long as `has_next?` returns true.
61
-
62
- You can always go about the manual way as per Amazon's docs:
63
-
64
- next_response = mws.orders.list_orders_by_next_response :next_token => response.next_token
67
+ Repeat as necessary. You can keep calling `next` on the API instance as long as `has_next?` returns true.
65
68
 
66
- ### Underscore notation
69
+ Or if you need to, you can save the next_token and go about the manual way as per Amazon's docs:
67
70
 
68
- ruby-mws wraps Amazon's CamelCase convention with Ruby-friendly underscore notation. This goes for request names and params, as well as response field names.
71
+ next_response = mws.orders.list_orders_by_next_token :next_token => response.next_token
69
72
 
70
- Available Requests
71
- ------------------
73
+ API
74
+ ---
72
75
 
73
- @mws = MWS.new(authentication_hash) # initialize the connection object
76
+ @mws = MWS.new(authentication_hash) # initialize the connection object (see above)
74
77
 
75
78
  This object can be used to access all API services. Below are examples on how to make the different requests that are available so far. Refer to the [Amazon MWS Reference Docs](https://developer.amazonservices.com/) for available fields for each request.
76
79
 
77
80
  ### Orders API
78
81
 
79
- * ListOrders - gets orders by time frame and other parameters
82
+ * ListOrders - gets orders by time range and other parameters
80
83
 
81
- `@mws.orders.list_orders :last_updated_after => Time.now-4.hours`
84
+ `@mws.orders.list_orders :last_updated_after => Time.now-4.hours, :order_status => 'Shipped'`
82
85
 
83
86
  * GetOrder - gets orders by Amazon order ID
84
87
 
@@ -86,7 +89,7 @@ This object can be used to access all API services. Below are examples on how to
86
89
 
87
90
  `:amazon_order_id` can be an array to retrieve multiple orders.
88
91
 
89
- * ListOrderItems - gets order items for one order ID
92
+ * ListOrderItems - gets order items for one order ID (only one order at a time here)
90
93
 
91
94
  `@mws.orders.list_order_items :amazon_order_id => "002-EXAMPLE-0031387"`
92
95
 
@@ -94,5 +97,5 @@ This object can be used to access all API services. Below are examples on how to
94
97
 
95
98
  * ListInventorySupply - returns availability of inventory, only returns items based on list of SKUs or last change date
96
99
 
97
- `@mws.inventory.list_inventory_supply :seller_skus => %w[PF-5VZN-04XR V4-03EY-LAL1 OC-TUKC-031P`
100
+ `@mws.inventory.list_inventory_supply :seller_skus => ['PF-5VZN-04XR', 'V4-03EY-LAL1', 'OC-TUKC-031P']`
98
101
  `@mws.inventory.list_inventory_supply :query_start_date_time => Time.now-1.day`
data/bin/ruby-mws ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'ruby-mws'
@@ -22,9 +22,8 @@ module MWS
22
22
 
23
23
  def self.def_request(requests, *options)
24
24
  [requests].flatten.each do |name|
25
- # class variable = a way to store options splat to pass into pseudomethod
26
- self.class_variable_set("@@#{name}_options", options.first)
27
25
  self.class_eval %Q{
26
+ @@#{name}_options = options.first
28
27
  def #{name}(params={})
29
28
  send_request(:#{name}, params, @@#{name}_options)
30
29
  end
@@ -47,18 +46,11 @@ module MWS
47
46
  params[:lists][:marketplace_id] = "MarketplaceId.Id"
48
47
 
49
48
  query = Query.new params
50
- @response = Response.new self.class.send(params[:verb], query.request_uri)
51
-
52
- begin
53
- res = @response.send("#{name}_response").send("#{name}_result")
54
- if @next[:token] = res.next_token # modifying, not comparing
55
- @next[:action] = params[:next_action] || (name.match(/_by_next_token/) ? name : "#{name}_by_next_token")
56
- end
57
- params[:mods].each {|mod| mod.call(res) } if params[:mods]
58
- res
59
- rescue NoMethodError
60
- @response
49
+ @response = Response.parse self.class.send(params[:verb], query.request_uri), name, params
50
+ if @response.respond_to?(:next_token) and @next[:token] = @response.next_token # modifying, not comparing
51
+ @next[:action] = name.match(/_by_next_token/) ? name : "#{name}_by_next_token"
61
52
  end
53
+ @response
62
54
  end
63
55
 
64
56
  def has_next?
@@ -2,14 +2,15 @@ module MWS
2
2
  module API
3
3
 
4
4
  class Order < Base
5
-
6
-
7
5
  def_request [:list_orders, :list_orders_by_next_token],
8
6
  :verb => :get,
9
7
  :uri => '/Orders/2011-01-01',
10
8
  :version => '2011-01-01',
9
+ :lists => {
10
+ :order_status => "OrderStatus.Status"
11
+ },
11
12
  :mods => [
12
- lambda {|r| r.orders = r.orders.order}
13
+ lambda {|r| r.orders = r.orders.order if r.orders}
13
14
  ]
14
15
 
15
16
  def_request [:list_order_items, :list_order_items_by_next_token],
@@ -2,7 +2,26 @@ module MWS
2
2
  module API
3
3
 
4
4
  class Response < Hashie::Rash
5
- # Just a wrapper for the Hashie class
5
+
6
+ def self.parse(hash, name, params)
7
+ rash = self.new(hash)
8
+ handle_error_response(rash["error_response"]["error"]) unless rash["error_response"].nil?
9
+ raise BadResponseError, "received non-matching response type #{rash.keys}" if rash["#{name}_response"].nil?
10
+ rash = rash["#{name}_response"]
11
+
12
+ if rash = rash["#{name}_result"]
13
+ # only runs mods if correct result is present
14
+ params[:mods].each {|mod| mod.call(rash) } if params[:mods]
15
+ rash
16
+ end
17
+ end
18
+
19
+ def self.handle_error_response(error)
20
+ msg = "#{error.code}: #{error.message}"
21
+ msg << " -- #{error.detail}" unless error.detail.nil?
22
+ raise ErrorResponse, msg
23
+ end
24
+
6
25
  end
7
26
 
8
27
  end
@@ -9,4 +9,9 @@ module MWS
9
9
  class NoNextToken < MWSException
10
10
  end
11
11
 
12
+ class ErrorResponse < MWSException
13
+ end
14
+
15
+ class BadResponseError < MWSException
16
+ end
12
17
  end
@@ -1,3 +1,3 @@
1
1
  module MWS
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -5,7 +5,7 @@ describe MWS::API::Inventory do
5
5
  before :all do
6
6
  EphemeralResponse.activate
7
7
  @mws = MWS.new(auth_params)
8
- @timestamp = "2012-01-15T18:07:48-05:00"
8
+ @timestamp = "2012-04-25T21:42:11-04:00"
9
9
  end
10
10
 
11
11
  context "requests" do
@@ -5,16 +5,16 @@ describe MWS::API::Order do
5
5
  before :all do
6
6
  EphemeralResponse.activate
7
7
  @mws = MWS.new(auth_params)
8
- @timestamp = "2012-01-15T17:28:17-05:00"
8
+ @timestamp = "2012-04-25T21:42:55-04:00"
9
9
  end
10
10
 
11
11
  context "requests" do
12
12
  describe "list_orders" do
13
- it "should receive a list_orders_result" do
13
+ it "should receive a list of orders" do
14
14
  orders = @mws.orders.list_orders :last_updated_after => "2012-01-15T13:07:26-05:00" ,
15
15
  :timestamp => @timestamp
16
16
  orders.orders.should be_an_instance_of Array
17
- orders.should == @mws.orders.response.list_orders_response.list_orders_result
17
+ orders.orders.first.should have_key :amazon_order_id
18
18
  end
19
19
  end
20
20
 
@@ -23,6 +23,7 @@ describe MWS::API::Order do
23
23
  orders = @mws.orders.list_orders_by_next_token :timestamp => @timestamp,
24
24
  :next_token => "zwR7fTkqiKp/YYuZQbKv1QafEPREmauvizt1MIhPYZZl3LSdPSOgN1byEfyVqilNBpcRD1uxgRxTg2dsYWmzKd8ytOVgN7d/KyNtf5fepe2OEd7gVZif6X81/KsTyqd1e64rGQd1TyCS68vI7Bqws+weLxD7b1CVZciW6QBe7o2FizcdzSXGSiKsUkM4/6QGllhc4XvGqg5e0zIeaOVNezxWEXvdeDL7eReo//Hc3LMRF18hF5ZYNntoCB8irbDGcVkxA+q0fZYwE7+t4NjazyEZY027dXAVTSGshRBy6ZTthhfBGj6Dwur8WCwcU8Vc25news0zC1w6gK1h3EdXw7a3u+Q12Uw9ZROnI57RGr4CrtRODNGKSRdGvNrxcHpI2aLZKrJa2MgKRa+KsojCckrDiHqb8mBEJ88g6izJN42dQcLTGQRwBej+BBOOHYP4"
25
25
  orders.orders.should be_an_instance_of Array
26
+ orders.orders.first.should have_key :amazon_order_id
26
27
  end
27
28
  end
28
29
 
@@ -40,6 +41,7 @@ describe MWS::API::Order do
40
41
  :timestamp => @timestamp
41
42
  orders.orders.should be_an_instance_of Array
42
43
  orders.orders.size.should == 2
44
+ orders.orders.first.should have_key :amazon_order_id
43
45
  end
44
46
  end
45
47
 
data/spec/spec_helper.rb CHANGED
@@ -14,12 +14,12 @@ RSpec.configure do |config|
14
14
  @mws_object ||= MWS.new(auth_params)
15
15
  end
16
16
 
17
+ # To test, create spec/credentials.yml or fill in below
17
18
  def auth_params
18
19
  @auth_params ||=
19
20
  begin
20
21
  hsh = YAML.load(File.open(File.join(File.expand_path(File.dirname(__FILE__)), 'credentials.yml'))).symbolize_keys!
21
22
  rescue
22
- # some fake auth values
23
23
  {
24
24
  :aws_access_key_id => 'access',
25
25
  :secret_access_key => 'super_secret',
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-mws
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-01-16 00:00:00.000000000 Z
12
+ date: 2013-01-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &70242944939120 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,15 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70242944939120
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: ephemeral_response
27
- requirement: &70242944938600 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ! '>='
@@ -32,10 +37,15 @@ dependencies:
32
37
  version: '0'
33
38
  type: :development
34
39
  prerelease: false
35
- version_requirements: *70242944938600
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
36
46
  - !ruby/object:Gem::Dependency
37
47
  name: httparty
38
- requirement: &70242944938020 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
39
49
  none: false
40
50
  requirements:
41
51
  - - ! '>='
@@ -43,10 +53,15 @@ dependencies:
43
53
  version: '0'
44
54
  type: :runtime
45
55
  prerelease: false
46
- version_requirements: *70242944938020
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
47
62
  - !ruby/object:Gem::Dependency
48
63
  name: nokogiri
49
- requirement: &70242944937380 !ruby/object:Gem::Requirement
64
+ requirement: !ruby/object:Gem::Requirement
50
65
  none: false
51
66
  requirements:
52
67
  - - ! '>='
@@ -54,10 +69,15 @@ dependencies:
54
69
  version: '0'
55
70
  type: :runtime
56
71
  prerelease: false
57
- version_requirements: *70242944937380
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
58
78
  - !ruby/object:Gem::Dependency
59
79
  name: ruby-hmac
60
- requirement: &70242944936700 !ruby/object:Gem::Requirement
80
+ requirement: !ruby/object:Gem::Requirement
61
81
  none: false
62
82
  requirements:
63
83
  - - ! '>='
@@ -65,10 +85,15 @@ dependencies:
65
85
  version: '0'
66
86
  type: :runtime
67
87
  prerelease: false
68
- version_requirements: *70242944936700
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
69
94
  - !ruby/object:Gem::Dependency
70
95
  name: hashie
71
- requirement: &70242944936280 !ruby/object:Gem::Requirement
96
+ requirement: !ruby/object:Gem::Requirement
72
97
  none: false
73
98
  requirements:
74
99
  - - ! '>='
@@ -76,10 +101,15 @@ dependencies:
76
101
  version: '0'
77
102
  type: :runtime
78
103
  prerelease: false
79
- version_requirements: *70242944936280
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
80
110
  - !ruby/object:Gem::Dependency
81
111
  name: rash
82
- requirement: &70242944935840 !ruby/object:Gem::Requirement
112
+ requirement: !ruby/object:Gem::Requirement
83
113
  none: false
84
114
  requirements:
85
115
  - - ! '>='
@@ -87,21 +117,27 @@ dependencies:
87
117
  version: '0'
88
118
  type: :runtime
89
119
  prerelease: false
90
- version_requirements: *70242944935840
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
91
126
  description: (Under development) This gem serves as a wrapper for Amazon.com's Marketplace
92
127
  Web Service (MWS) API. Visit http://github.com/elyngved/ruby-mws for documentation.
93
128
  email:
94
129
  - elyngved@gmail.com
95
- executables: []
130
+ executables:
131
+ - ruby-mws
96
132
  extensions: []
97
133
  extra_rdoc_files: []
98
134
  files:
99
135
  - .gitignore
100
- - .rvmrc
101
136
  - Gemfile
102
137
  - LICENSE
103
138
  - README.markdown
104
139
  - Rakefile
140
+ - bin/ruby-mws
105
141
  - lib/ruby-mws.rb
106
142
  - lib/ruby-mws/api/base.rb
107
143
  - lib/ruby-mws/api/inventory.rb
@@ -142,7 +178,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
142
178
  version: '0'
143
179
  requirements: []
144
180
  rubyforge_project: ruby-mws
145
- rubygems_version: 1.8.15
181
+ rubygems_version: 1.8.23
146
182
  signing_key:
147
183
  specification_version: 3
148
184
  summary: RubyMWS Gem
@@ -156,3 +192,4 @@ test_files:
156
192
  - spec/ruby-mws/base_spec.rb
157
193
  - spec/ruby-mws/connection_spec.rb
158
194
  - spec/spec_helper.rb
195
+ has_rdoc:
data/.rvmrc DELETED
@@ -1 +0,0 @@
1
- rvm use ruby-1.9.3-p0@ruby-mws