otis 0.0.4 → 0.0.5

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.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NjNlNDM2YzIxMTJhOTU3M2QzMjRjMTFjM2ZiOGVhYjc3N2NmYTRmYw==
5
+ data.tar.gz: !binary |-
6
+ NWJmNjRiNDk0YmY3NTdkOTA5NzY2ZjEwOTAyYjk4NTczNGNkYzVjZg==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ ZmZlYzU1M2E5MzYxYTg0MmI3NDI4MDBhMzBkNDcwZDUxM2IyNWQxNGRlMWNi
10
+ NDk1NThmYTVkMjIzNTM4MDZlMDM0YWJjYTBkYjdmNTJkZmNiZDhhZmY4ZmUz
11
+ NTMzMGFhMzY4ZmJlMGUyZTI4NTJlZDM3ZDRmNWRjMWRjNzk2YTc=
12
+ data.tar.gz: !binary |-
13
+ Yzg3NjgxYTc4YTJlN2MxZGU5Y2M4M2Y4YWE5NzkxN2RhYTgyMzQ3NzZlZjE5
14
+ MGE5NzZiMTM3YWZhOWYzMGM0OTFkZTJjNzRlZDk2ZTUxOWQzZDM0NWZlOTk0
15
+ YjhlOTc0ZmEzNzNjMGEzODJkYjE0ZjQwODNlODc1MzY4YzlkZmI=
data/README.md CHANGED
@@ -32,10 +32,12 @@ Using the example of [US Zip webservice](https://github.com/tbueno/otis_uszip_ex
32
32
  })
33
33
 
34
34
  ### Client
35
- Otis offers a base Client class that handle the response and instantiates the response object accordingly.
35
+ Otis offers a base Client class that handle the response and instantiates the response object accordingly. In the following example, a SOAP client is instantiated with the proper WSDL
36
36
 
37
37
  Otis::Client.new(routes, "http://www.webservicex.net/uszip.asmx?WSDL")
38
38
 
39
+ HTTP clients can also be used as well
40
+
39
41
  ### Model
40
42
 
41
43
  The Client takes care of transforming the API response into a Hash. Having hashes, makes it easy to create response objects, called Otis::Model.
@@ -6,8 +6,10 @@ module Otis
6
6
  require 'otis/hash_content'
7
7
  require 'otis/otis_object'
8
8
  require 'otis/model'
9
+ require 'otis/hooks'
9
10
  require 'otis/client'
10
11
  require 'otis/http_client'
11
12
  require 'otis/soap_client'
12
13
  require 'otis/map'
14
+ require 'otis/response'
13
15
  end
@@ -1,12 +1,19 @@
1
1
  module Otis
2
2
  class Client
3
+ include Hooks
4
+
3
5
  protected
4
6
  # Tries to find the requested method in the routes map.
5
7
  # Send it to Object$method_missing if the desired route is not found
6
8
  def method_missing(meth, *args)
7
9
  klass = @routes[meth.to_sym]
8
10
  super unless klass
9
- klass.new(call(meth, args))
11
+ if respond_to?("filter_for_#{meth}")
12
+ filter_meth = send("filter_for_#{meth}")
13
+ send(filter_meth, call(meth, *args))
14
+ else
15
+ klass.new(call(meth, *args))
16
+ end
10
17
  end
11
18
  end
12
19
  end
@@ -0,0 +1,23 @@
1
+ module Otis
2
+ module Hooks
3
+
4
+ def self.included(base)
5
+ base.extend(ClassExtension)
6
+ end
7
+
8
+ module ClassExtension
9
+ #
10
+ # Filter the response of a method with another method
11
+ #
12
+ def filter(meth, options = {})
13
+ meth = meth.to_s
14
+ class_eval %(
15
+ def filter_for_#{meth}
16
+ "#{options[:with]}"
17
+ end
18
+ )
19
+ end
20
+ end
21
+ end
22
+
23
+ end
@@ -12,9 +12,14 @@ module Otis
12
12
  end
13
13
 
14
14
  protected
15
- def call(action, options)
16
- response = @client.get "#{options.first}/#{action}", options.last
17
- JSON.parse(response.body)
15
+ def call(action, url, options)
16
+ response = @client.get "#{url}", options, {'Content-Type' => 'application/json'}
17
+ respond(response)
18
+ end
19
+
20
+ #TODO: make it more robust
21
+ def respond(response)
22
+ response.status == 304 ? {} : JSON.parse(response.body).merge(headers: response.headers)
18
23
  end
19
24
 
20
25
  def create_client(url)
@@ -1,7 +1,9 @@
1
1
  module Otis
2
2
  class Model
3
- include Otis::Object
4
3
  include Virtus.model
4
+ include Otis::Object
5
5
  include HashContent
6
+
7
+ attributes :headers
6
8
  end
7
9
  end
@@ -10,11 +10,6 @@ module Otis
10
10
  attrs.each_pair do |k, v|
11
11
  m = underscore(k.to_s)
12
12
  self.send("#{m}=", v ) if self.respond_to?("#{m}=")
13
- end if respond_to?(:decamelize?) and decamelize?
14
- if respond_to?(:hooks)
15
- hooks.each do |hook|
16
- self.send(hook)
17
- end
18
13
  end
19
14
  end
20
15
 
@@ -24,6 +19,19 @@ module Otis
24
19
  class_eval %(attr_accessor :#{m} )
25
20
  end
26
21
  end
22
+
23
+ def collection(opts ={})
24
+ collection = opts[:as].to_s
25
+ klass = opts[:of]
26
+ class_eval %(def #{collection}; @#{collection} ||= Array(@response['#{camelize(collection)}']).map{|c| #{klass}.new(c)}; end)
27
+ end
28
+
29
+ private
30
+ def camelize(string)
31
+ return string if string !~ /_/ && self =~ /[A-Z]+.*/
32
+ string.split('_').map{|e| e.capitalize}.join
33
+ end
34
+
27
35
  end
28
36
 
29
37
  private
@@ -0,0 +1,4 @@
1
+ module Otis
2
+ class Response < Otis::Model
3
+ end
4
+ end
@@ -1,3 +1,3 @@
1
1
  module Otis
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
@@ -21,6 +21,7 @@ Gem::Specification.new do |spec|
21
21
  spec.add_development_dependency "bundler", "~> 1.3"
22
22
  spec.add_development_dependency "rake"
23
23
  spec.add_development_dependency "debugger"
24
+ spec.add_development_dependency "rspec"
24
25
 
25
26
  spec.add_dependency 'savon', '~> 2.2.0'
26
27
  spec.add_dependency 'faraday'
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe Otis::Hooks do
4
+
5
+
6
+ class TestClient < Otis::Client
7
+ filter :my_method, with: :my_filter
8
+ def initialize(routes); @routes = routes; end
9
+ def my_filter(content); content[:foo].upcase! ;end
10
+ def call(action, url, options)
11
+ {foo: 'bar'}
12
+ end
13
+ end
14
+
15
+ describe 'filter' do
16
+
17
+ let(:response) { double }
18
+
19
+ it 'executes filters with results of method' do
20
+ object = TestClient.new(my_method: response)
21
+ expect(object.my_method(double, double)).to eq('BAR')
22
+ end
23
+ end
24
+
25
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe Otis::HashContent do
4
+ describe 'accessor generation' do
5
+ let(:params) do {a: {b: {foo: 'bar'}}} end
6
+
7
+ class ComplexClass < Otis::Model
8
+ root_key to: [:a, :b]
9
+ attribute :foo, String
10
+ end
11
+
12
+ it 'creates an array to the root key' do
13
+ ComplexClass.new(params).path.should == [:a, :b]
14
+ end
15
+
16
+ it 'sets the root key' do
17
+ ComplexClass.new(params).foo.should == 'bar'
18
+ end
19
+ end
20
+
21
+ describe 'remaping root key name' do
22
+
23
+ let(:params) do {a: {b: {foo: 'bar'}}} end
24
+
25
+ class EvenMoreComplex < Otis::Model
26
+ root_key to: [:a, :b], as: 'baz'
27
+ attribute :baz, String
28
+ end
29
+
30
+ it 'response accordingly' do
31
+ EvenMoreComplex.new(params).baz.should == {foo: 'bar'}
32
+ end
33
+ end
34
+ end
@@ -23,7 +23,7 @@ describe Otis::HttpClient do
23
23
  let(:url) { 'http://api.site.com' }
24
24
 
25
25
  it 'instantiate a faraday client with endpoint url' do
26
- Faraday.should_receive(:new).with(url: url)
26
+ expect(Faraday).to receive(:new).with(url: url)
27
27
  described_class.new(map, url)
28
28
  end
29
29
 
@@ -47,25 +47,28 @@ describe Otis::HttpClient do
47
47
 
48
48
  describe 'call' do
49
49
 
50
- let(:faraday) { double(get: response) }
51
- let(:response) { double(body: "{\"my_call\": \"response\"}")}
52
- let(:routes) { Otis::Map.new({my_call: ResponseClass}) }
50
+ let(:faraday) { double(get: response) }
51
+ let(:url) { 'api/v1' }
52
+ let(:params) { { param1: 'foo', param2: 'bar' } }
53
+ let(:response) { double(body: "{ \"my_call\": \"response\"}",
54
+ status: 200, headers: {}) }
55
+ let(:routes) { Otis::Map.new({ my_call: ResponseClass } ) }
53
56
 
54
57
  before { Otis::HttpClient.any_instance.stub(create_client: faraday)}
55
58
 
56
59
  it 'forwards the call to the client' do
57
- faraday.should_receive(:get).with("api/v1/my_call", {param1: 'foo', param2: 'bar'})
58
- MyHttpClient.new(routes, 'url').my_call('api/v1', {param1: 'foo', param2: 'bar'})
60
+ expect(faraday).to receive(:get).with(url, params, {'Content-Type' => 'application/json'})
61
+ MyHttpClient.new(routes, 'url').my_call(url, params)
59
62
  end
60
63
 
61
64
  it 'returns response object' do
62
- MyHttpClient.new(routes, 'url').my_call('api/v1', {param1: 'foo', param2: 'bar'})
63
- .should be_a(ResponseClass)
65
+ expect(MyHttpClient.new(routes, 'url').my_call(url, params))
66
+ .to be_a(ResponseClass)
64
67
  end
65
68
 
66
69
  it 'passes the parsed response to response object' do
67
- ResponseClass.should_receive(:new).with({'my_call' => 'response'})
68
- MyHttpClient.new(routes, 'url').my_call('api/v1', {param1: 'foo', param2: 'bar'})
70
+ ResponseClass.should_receive(:new).with({'my_call' => 'response', :headers => {}})
71
+ MyHttpClient.new(routes, 'url').my_call(url, params)
69
72
  end
70
73
  end
71
74
 
@@ -13,35 +13,4 @@ describe Otis::Model do
13
13
  end
14
14
  end
15
15
  end
16
-
17
- describe 'accessor generation' do
18
- let(:params) do {a: {b: {foo: 'bar'}}} end
19
-
20
- class ComplexClass < Otis::Model
21
- root_key to: [:a, :b]
22
- attribute :foo, String
23
- end
24
-
25
- it 'creates an array to the root key' do
26
- ComplexClass.new(params).path.should == [:a, :b]
27
- end
28
-
29
- it 'sets the root key' do
30
- ComplexClass.new(params).foo.should == 'bar'
31
- end
32
- end
33
-
34
- describe 'remaping root key name' do
35
-
36
- let(:params) do {a: {b: {foo: 'bar'}}} end
37
-
38
- class EvenMoreComplex < Otis::Model
39
- root_key to: [:a, :b], as: 'baz'
40
- attribute :baz, String
41
- end
42
-
43
- it 'response accordingly' do
44
- EvenMoreComplex.new(params).baz.should == {foo: 'bar'}
45
- end
46
- end
47
16
  end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe Otis::Object do
4
+
5
+ describe 'collection' do
6
+ class Thing; end
7
+
8
+ class TestClass
9
+ include Otis::Object
10
+ collection of: Thing, as: :things
11
+ end
12
+ let(:klass) { TestClass.new }
13
+
14
+ it 'creates the get' do
15
+ expect(klass).to respond_to(:things)
16
+ end
17
+
18
+ it 'holds a collection' do
19
+ klass.things << Thing.new
20
+ klass.things << Thing.new
21
+ expect(klass.things.count).to eq(2)
22
+ end
23
+ end
24
+ end
@@ -23,7 +23,7 @@ describe Otis::SoapClient do
23
23
  before { client.stub_chain(:call, :body).and_return(response) }
24
24
 
25
25
  it 'delegates the call the the client' do
26
- client.should_receive(:call).with(:my_call, {params: []})
26
+ client.should_receive(:call).with(:my_call, [:params, []])
27
27
  MySoapClient.new(routes, double).my_call(params: [])
28
28
  end
29
29
 
metadata CHANGED
@@ -1,20 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: otis
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
5
- prerelease:
4
+ version: 0.0.5
6
5
  platform: ruby
7
6
  authors:
8
7
  - Thiago Bueno
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-11-12 00:00:00.000000000 Z
11
+ date: 2014-02-25 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: bundler
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
17
  - - ~>
20
18
  - !ruby/object:Gem::Version
@@ -22,7 +20,6 @@ dependencies:
22
20
  type: :development
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
24
  - - ~>
28
25
  - !ruby/object:Gem::Version
@@ -30,7 +27,6 @@ dependencies:
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: rake
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
31
  - - ! '>='
36
32
  - !ruby/object:Gem::Version
@@ -38,7 +34,6 @@ dependencies:
38
34
  type: :development
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
38
  - - ! '>='
44
39
  - !ruby/object:Gem::Version
@@ -46,7 +41,6 @@ dependencies:
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: debugger
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
45
  - - ! '>='
52
46
  - !ruby/object:Gem::Version
@@ -54,7 +48,20 @@ dependencies:
54
48
  type: :development
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
58
65
  requirements:
59
66
  - - ! '>='
60
67
  - !ruby/object:Gem::Version
@@ -62,7 +69,6 @@ dependencies:
62
69
  - !ruby/object:Gem::Dependency
63
70
  name: savon
64
71
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
72
  requirements:
67
73
  - - ~>
68
74
  - !ruby/object:Gem::Version
@@ -70,7 +76,6 @@ dependencies:
70
76
  type: :runtime
71
77
  prerelease: false
72
78
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
79
  requirements:
75
80
  - - ~>
76
81
  - !ruby/object:Gem::Version
@@ -78,7 +83,6 @@ dependencies:
78
83
  - !ruby/object:Gem::Dependency
79
84
  name: faraday
80
85
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
86
  requirements:
83
87
  - - ! '>='
84
88
  - !ruby/object:Gem::Version
@@ -86,7 +90,6 @@ dependencies:
86
90
  type: :runtime
87
91
  prerelease: false
88
92
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
93
  requirements:
91
94
  - - ! '>='
92
95
  - !ruby/object:Gem::Version
@@ -94,7 +97,6 @@ dependencies:
94
97
  - !ruby/object:Gem::Dependency
95
98
  name: virtus
96
99
  requirement: !ruby/object:Gem::Requirement
97
- none: false
98
100
  requirements:
99
101
  - - ! '>='
100
102
  - !ruby/object:Gem::Version
@@ -102,7 +104,6 @@ dependencies:
102
104
  type: :runtime
103
105
  prerelease: false
104
106
  version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
107
  requirements:
107
108
  - - ! '>='
108
109
  - !ruby/object:Gem::Version
@@ -123,44 +124,51 @@ files:
123
124
  - lib/otis.rb
124
125
  - lib/otis/client.rb
125
126
  - lib/otis/hash_content.rb
127
+ - lib/otis/hooks.rb
126
128
  - lib/otis/http_client.rb
127
129
  - lib/otis/map.rb
128
130
  - lib/otis/model.rb
129
131
  - lib/otis/otis_object.rb
132
+ - lib/otis/response.rb
130
133
  - lib/otis/soap_client.rb
131
134
  - lib/otis/version.rb
132
135
  - otis.gemspec
136
+ - spec/lib/otis/client_spec.rb
137
+ - spec/lib/otis/hash_content_spec.rb
133
138
  - spec/lib/otis/http_client_spec.rb
134
139
  - spec/lib/otis/model_spec.rb
140
+ - spec/lib/otis/otis_object_spec.rb
135
141
  - spec/lib/otis/soap_client_spec.rb
136
142
  - spec/spec_helper.rb
137
143
  homepage: ''
138
144
  licenses:
139
145
  - MIT
146
+ metadata: {}
140
147
  post_install_message:
141
148
  rdoc_options: []
142
149
  require_paths:
143
150
  - lib
144
151
  required_ruby_version: !ruby/object:Gem::Requirement
145
- none: false
146
152
  requirements:
147
153
  - - ! '>='
148
154
  - !ruby/object:Gem::Version
149
155
  version: '0'
150
156
  required_rubygems_version: !ruby/object:Gem::Requirement
151
- none: false
152
157
  requirements:
153
158
  - - ! '>='
154
159
  - !ruby/object:Gem::Version
155
160
  version: '0'
156
161
  requirements: []
157
162
  rubyforge_project:
158
- rubygems_version: 1.8.23
163
+ rubygems_version: 2.1.11
159
164
  signing_key:
160
- specification_version: 3
165
+ specification_version: 4
161
166
  summary: A Ruby Api wrapper framework
162
167
  test_files:
168
+ - spec/lib/otis/client_spec.rb
169
+ - spec/lib/otis/hash_content_spec.rb
163
170
  - spec/lib/otis/http_client_spec.rb
164
171
  - spec/lib/otis/model_spec.rb
172
+ - spec/lib/otis/otis_object_spec.rb
165
173
  - spec/lib/otis/soap_client_spec.rb
166
174
  - spec/spec_helper.rb