Skip to content

Commit

Permalink
Introduce bang methods which raise exceptions when API returns errors
Browse files Browse the repository at this point in the history
e.g.: mws_api.subscriptions.register_destination!(...)
Deprecate old methods (with no bangs)
  • Loading branch information
vbyno committed Jun 4, 2019
1 parent 4fbc863 commit b37992e
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 6 deletions.
5 changes: 3 additions & 2 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,14 @@ Using in a simple ruby file:
To access the apis you can use:

```ruby
mws_api._api_name_._action_to_calll(params={})
mws_api._api_name_._action_to_call!(params={})
```
The method above will return an error if any `ErrorResponse` is returned from MWS

Let's say we want to retrieve a list of orders using MWS orders api:

```ruby
mws_api.orders.list_orders(
mws_api.orders.list_orders!(
"MarketplaceId.Id.1" => "marketplace id",
created_after: Time.new(2013, 1, 1)
)
Expand Down
1 change: 1 addition & 0 deletions lib/mws.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

require_relative 'mws/query'
require_relative 'mws/connection'
require_relative 'mws/api'
require_relative 'mws/api/base'
require_relative 'mws/api/orders'
require_relative 'mws/api/reports'
Expand Down
8 changes: 8 additions & 0 deletions lib/mws/api.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module MWS
# API module
module API
ResponseError = Class.new(StandardError)

RESPONSE_ERROR_KEY = 'ErrorResponse'.freeze
end
end
22 changes: 22 additions & 0 deletions lib/mws/api/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class Base
# TODO: Temporary solution, move to configuration
DEFAULT_TIMEOUT = 2000
USER_AGENT = 'User-Agent'.freeze
STRICT_MEHTHOD_ENDING = '!'.freeze

def initialize(connection)
@verb ||= :get
Expand Down Expand Up @@ -43,19 +44,40 @@ def build_query_from_params(action, params)

def method_missing(name, *args)
if self.class::ACTIONS.include?(name)
warn "[DEPRECATION] `#{name}` will be removed in next major version. " \
"Please use `#{name}!` instead."

call(name, *args)
elsif self.class::ACTIONS.include?(method_without_bang(name))
response = call(method_without_bang(name), *args)

return response unless response.key?(MWS::API::RESPONSE_ERROR_KEY)

raise MWS::API::ResponseError, response.to_json
else
super
end
end

def respond_to_missing?(name, include_private = false)
self.class::ACTIONS.include?(name) ||
self.class::ACTIONS.include?(method_without_bang(name)) ||
super
end

def http_request_options
@http_request_options ||= begin
options = { timeout: DEFAULT_TIMEOUT }
options.merge!(headers: { USER_AGENT => MWS.user_agent }) if MWS.user_agent.present?
options
end
end

private

def method_without_bang(name)
name.to_s.chomp(STRICT_MEHTHOD_ENDING).to_sym
end
end
end
end
83 changes: 79 additions & 4 deletions spec/mws-rb/api/base_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,89 @@ def initialize(connection)
end

describe 'method_missing to call actions' do
before(:each) { allow(HTTParty).to receive(:get).and_return({}) }
before(:each) { allow(HTTParty).to receive(:get).and_return(result) }

it 'should raise exception if Actions do not contain the action name' do
expect { test_api.action_not_found }.to raise_error(NoMethodError)
context 'regular method call' do
let(:result) { {} }
let(:expected_deprication_warning) do
'[DEPRECATION] `test_action` will be removed in next major version. ' \
"Please use `test_action!` instead.\n"
end

it 'should raise exception if Actions do not contain the action name', :stub_stdout do
expect { test_api.action_not_found }.to raise_error(NoMethodError)
end

it 'makes api call and return result if Actions contain the action name', :stub_stdout do
expect(test_api.test_action).to eq result
end

it 'prints a deprication warning' do
expect { test_api.test_action }
.to output(expected_deprication_warning)
.to_stderr
end
end

context 'bang method' do
context 'API response does not contain errors' do
let(:result) { {} }

it 'raises exception if Actions do not contain the action name' do
expect { test_api.action_not_found! }.to raise_error(NoMethodError)
end

it 'makes api call and return result if Actions contain the action name' do
expect(test_api.test_action!).to eq result
end
end

context 'API response contains errors' do
let(:result) { { 'ErrorResponse' => {} } }

it 'makes api call and returns error' do
expect { test_api.test_action! }
.to raise_error MWS::API::ResponseError, '{"ErrorResponse":{}}'
end
end
end
end

describe '#respond_to_missing?' do
subject { test_api.respond_to?(method_name) }

context 'Actions contain method' do
let(:method_name) { 'test_action' }

it { is_expected.to be true }
end

context 'Actions do not contain method' do
let(:method_name) { 'missed_test_action' }

it { is_expected.to be false }
end

context 'Actions contain bang method' do
let(:method_name) { 'test_action!' }

it { is_expected.to be true }
end

context 'Actions do not contain bang method' do
let(:method_name) { 'missed_test_action!' }

it { is_expected.to be false }
end

context 'regular Ruby method' do
let(:method_name) { 'nil?' }

it { is_expected.to be true }
end
end

context 'user agent' do
context 'user agent', :stub_stdout do
subject { test_api.test_action(params) }

before do |example|
Expand Down
6 changes: 6 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,10 @@
config.filter_sensitive_data('DUMMY_AWS_SELLER_ID') { ENV['AWS_SELLER_ID'] }
end

RSpec.configure do |config|
config.before(:each, :stub_stdout) do
allow_any_instance_of(Kernel).to receive(:warn)
end
end

RSpec.configure(&:raise_errors_for_deprecations!)

0 comments on commit b37992e

Please sign in to comment.