otis 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -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