morpheus 0.3.7 → 0.3.8

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -2,6 +2,9 @@
2
2
  *.gem
3
3
  *.rbc
4
4
  .bundle
5
+ .rvmrc
6
+ .rbenv-version
7
+ .rbenv-gemsets
5
8
  .config
6
9
  .yardoc
7
10
  Gemfile.lock
@@ -1,7 +1,10 @@
1
1
  module Morpheus
2
2
  module Client
3
3
  module Associations
4
- extend ActiveSupport::Concern
4
+
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ end
5
8
 
6
9
  module ClassMethods
7
10
 
@@ -13,5 +13,10 @@ module Morpheus
13
13
  attributes.keys if persisted?
14
14
  end
15
15
 
16
+ def to_partial_path
17
+ underscored_model_name = self.class.model_name.underscore
18
+ "#{underscored_model_name.pluralize}/#{underscored_model_name}"
19
+ end
20
+
16
21
  end
17
22
  end
@@ -9,67 +9,55 @@ module Morpheus
9
9
  end
10
10
 
11
11
  def self.parse(owner, request, metadata)
12
- parser = new(owner, request, metadata)
13
- ActiveSupport::Notifications.instrument('request.morpheus',
14
- :url => request.url,
15
- :params => request.params,
16
- :method => request.method,
17
- :class => owner,
18
- :response => request.response
19
- ) do
20
- @parsed_response = parser.parse
21
- end
22
- RequestCache.cache.clear unless request.method == :get
23
- @parsed_response
12
+ new(owner, request, metadata).parse
24
13
  end
25
14
 
26
15
  def parse
27
- case @response.code
28
- when 200..299
29
- build_from_response
30
- when 404
31
- raise_not_found
32
- when 422
33
- build_from_response
34
- when 500..599
35
- raise ServerError
36
- when 0
37
- raise RemoteHostConnectionFailure
38
- else
39
- raise InvalidResponseCode, "Response had error code: #{@response.code}"
16
+ clear_cache!
17
+ with_active_support_notifications do
18
+ case @response.code
19
+ when 200..299, 422
20
+ build_from_response
21
+ when 404
22
+ raise_not_found
23
+ when 500..599
24
+ raise ServerError
25
+ when 0
26
+ raise RemoteHostConnectionFailure
27
+ else
28
+ raise InvalidResponseCode, "Response had error code: #{@response.code}"
29
+ end
40
30
  end
41
31
  end
42
32
 
43
33
  private
44
34
 
45
- def content
46
- @content ||= Yajl::Parser.parse(@response.body).try(:[], 'content')
35
+ def with_active_support_notifications
36
+ ActiveSupport::Notifications.instrument('request.morpheus',
37
+ :url => @request.url,
38
+ :params => @request.params,
39
+ :method => @request.method,
40
+ :class => @owner,
41
+ :response => @request.response
42
+ ) { yield }
47
43
  end
48
44
 
49
- def response_errors
50
- @response_errors ||= Yajl::Parser.parse(@response.body).try(:[], 'errors')
45
+ def clear_cache!
46
+ RequestCache.cache.clear unless @request.method == :get
51
47
  end
52
48
 
53
49
  def build_from_response
54
50
  if content
55
51
  if Array === content
56
52
  content.collect do |attributes|
57
- obj = build_object_with_attributes(attributes)
53
+ build_object_with_attributes(attributes)
58
54
  end
59
55
  else
60
- obj = build_object_with_attributes(content)
56
+ build_object_with_attributes(content)
61
57
  end
62
58
  end
63
59
  end
64
60
 
65
- def build_object_with_attributes(attributes)
66
- if attributes.keys.include?('type')
67
- attributes['type'].constantize.new(attributes)
68
- else
69
- @requesting_class.new.send(:merge_attributes, attributes)
70
- end
71
- end
72
-
73
61
  def raise_not_found
74
62
  case
75
63
  when @metadata[:ids]
@@ -81,5 +69,25 @@ module Morpheus
81
69
  end
82
70
  end
83
71
 
72
+ def parsed_body
73
+ @parsed_body ||= Yajl::Parser.parse(@response.body)
74
+ end
75
+
76
+ def content
77
+ @content ||= parsed_body.try(:[], 'content')
78
+ end
79
+
80
+ def response_errors
81
+ @response_errors ||= parsed_body.try(:[], 'errors')
82
+ end
83
+
84
+ def build_object_with_attributes(attributes)
85
+ if attributes.keys.include?('type')
86
+ attributes['type'].constantize.new(attributes)
87
+ else
88
+ @requesting_class.new.send(:merge_attributes, attributes)
89
+ end
90
+ end
91
+
84
92
  end
85
93
  end
@@ -1,3 +1,3 @@
1
1
  module Morpheus
2
- VERSION = '0.3.7'
2
+ VERSION = '0.3.8'
3
3
  end
data/morpheus.gemspec CHANGED
@@ -1,5 +1,6 @@
1
1
  # -*- encoding: utf-8 -*-
2
- require File.expand_path('../lib/morpheus/version', __FILE__)
2
+ $:.unshift File.expand_path('../lib', __FILE__)
3
+ require 'morpheus/version'
3
4
 
4
5
  Gem::Specification.new do |gem|
5
6
  gem.authors = ['Ryan Moran']
@@ -17,13 +18,13 @@ Gem::Specification.new do |gem|
17
18
 
18
19
  gem.add_dependency 'yajl-ruby', '~> 0.8.2'
19
20
  gem.add_dependency 'typhoeus', '~> 0.2.4'
20
- gem.add_dependency 'activemodel', '> 3.0.0'
21
- gem.add_dependency 'activesupport', '> 3.0.0'
22
- gem.add_dependency 'i18n', '> 0.5.0'
21
+ gem.add_dependency 'activemodel', '>= 3.0.0'
22
+ gem.add_dependency 'activesupport', '>= 3.0.0'
23
+ gem.add_dependency 'i18n', '>= 0.5.0'
23
24
 
24
- gem.add_development_dependency 'rails', '> 3.0.0'
25
+ gem.add_development_dependency 'rails', '>= 3.0.0'
25
26
  gem.add_development_dependency 'sqlite3', '~> 1.3.3'
26
- gem.add_development_dependency 'rspec-rails', '~> 2.7.0'
27
+ gem.add_development_dependency 'rspec-rails', '~> 2.8.1'
27
28
  gem.add_development_dependency 'rcov', '~> 0.9.11'
28
- gem.add_development_dependency 'autotest-standalone', '~> 4.5.8'
29
+ gem.add_development_dependency 'autotest-standalone', '~> 4.5.9'
29
30
  end
@@ -63,4 +63,14 @@ describe Morpheus::Conversion do
63
63
  end
64
64
  end
65
65
 
66
+ describe '#to_partial_path' do
67
+ before(:each) do
68
+ @dog = Dog.new
69
+ end
70
+
71
+ it 'returns a string representing the path to a partial for this model' do
72
+ @dog.to_partial_path.should eql('dogs/dog')
73
+ end
74
+ end
75
+
66
76
  end
@@ -1,17 +1,235 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Morpheus::ResponseParser do
4
-
5
- describe '#initialize' do
6
- pending
7
- end
4
+ let(:owner) { Dog }
5
+ let(:response) { mock(:body => '{ "content": { "foo": "bar" }, "errors": [{ "foo": "cannot be \"bar\"" }] }') }
6
+ let(:request) { req = mock(:response => response, :url => '/dog/1', :params => { :id => 1 }); req.stub(:method).and_return(:get); req }
7
+ let(:metadata) { {} }
8
+ let(:parsed_response) { mock }
9
+ let(:parser) { Morpheus::ResponseParser.new(owner, request, metadata) }
8
10
 
9
11
  describe '.parse' do
10
- pending
12
+ before do
13
+ parser
14
+ Morpheus::ResponseParser.stub(:new).and_return(parser)
15
+ parser.stub(:parse).and_return(parsed_response)
16
+ end
17
+
18
+ it 'creates a new ResponseParser' do
19
+ Morpheus::ResponseParser.should_receive(:new).with(owner, request, metadata).and_return(parser)
20
+ Morpheus::ResponseParser.parse(owner, request, metadata)
21
+ end
22
+
23
+ it 'delegates parsing to the new ResponseParser' do
24
+ parser.should_receive(:parse)
25
+ Morpheus::ResponseParser.parse(owner, request, metadata)
26
+ end
27
+
28
+ it 'returns the parsed response' do
29
+ response = Morpheus::ResponseParser.parse(owner, request, metadata)
30
+ response.should eql(parsed_response)
31
+ end
11
32
  end
12
33
 
13
34
  describe '#parse' do
14
- pending
35
+ before do
36
+ parser.stub(:clear_cache!)
37
+ end
38
+
39
+ it 'clears the cache' do
40
+ parser.stub(:with_active_support_notifications)
41
+ parser.should_receive(:clear_cache!)
42
+ parser.parse
43
+ end
44
+
45
+ context 'when the response code is 200..299' do
46
+ before do
47
+ response.stub(:code).and_return(200)
48
+ end
49
+
50
+ it 'delegates to #build_from_response' do
51
+ parser.should_receive(:build_from_response)
52
+ parser.parse
53
+ end
54
+ end
55
+
56
+ context 'when the repsonse code is 404' do
57
+ before do
58
+ response.stub(:code).and_return(404)
59
+ end
60
+
61
+ it 'delegates to #raise_not_found' do
62
+ parser.should_receive(:raise_not_found)
63
+ parser.parse
64
+ end
65
+ end
66
+
67
+ context 'when the response code is 422' do
68
+ before do
69
+ response.stub(:code).and_return(422)
70
+ end
71
+
72
+ it 'delegates to #build_from_response' do
73
+ parser.should_receive(:build_from_response)
74
+ parser.parse
75
+ end
76
+ end
77
+
78
+ context 'when the response code is 500..599' do
79
+ before do
80
+ response.stub(:code).and_return(500)
81
+ end
82
+
83
+ it 'raises a ServerError exception' do
84
+ lambda { parser.parse }.should raise_error(Morpheus::ServerError)
85
+ end
86
+ end
87
+
88
+ context 'when the response code is 0' do
89
+ before do
90
+ response.stub(:code).and_return(0)
91
+ end
92
+
93
+ it 'raises a RemoteHostConnectionFailure exception' do
94
+ lambda { parser.parse }.should raise_error(Morpheus::RemoteHostConnectionFailure)
95
+ end
96
+ end
97
+
98
+ context 'when the response code is not one of the above' do
99
+ before do
100
+ response.stub(:code).and_return(701)
101
+ end
102
+
103
+ it 'raises an InvalidResponseCode exception' do
104
+ lambda { parser.parse }.should raise_error(Morpheus::InvalidResponseCode, 'Response had error code: 701')
105
+ end
106
+ end
107
+ end
108
+
109
+ describe '#clear_cache!' do
110
+ context 'when the request method is not GET' do
111
+ before do
112
+ request.stub(:method).and_return(:put)
113
+ end
114
+
115
+ it 'clears the RequestCache cache' do
116
+ Morpheus::RequestCache.cache.should_receive(:clear)
117
+ parser.send(:clear_cache!)
118
+ end
119
+ end
120
+
121
+ context 'when the request method is GET' do
122
+ before do
123
+ request.stub(:method).and_return(:get)
124
+ end
125
+
126
+ it 'does not clear the RequestCache cache' do
127
+ Morpheus::RequestCache.cache.should_not_receive(:clear)
128
+ parser.stub(:clear_cache!)
129
+ end
130
+ end
131
+ end
132
+
133
+ describe '#build_from_response' do
134
+ context 'when there is content' do
135
+ context 'when the content is an Array' do
136
+ let(:content) { [{ 'foo' => 'bar' }, { 'baz' => 'qux' }] }
137
+
138
+ before do
139
+ parser.stub(:content).and_return(content)
140
+ end
141
+
142
+ it 'delegates to #build_object_with_attributes for each element, collecting the results' do
143
+ parser.should_receive(:build_object_with_attributes).exactly(2).times
144
+ parser.send(:build_from_response)
145
+ end
146
+ end
147
+
148
+ context 'when the content is not an Array' do
149
+ let(:content) { { 'foo' => 'bar' } }
150
+
151
+ it 'delegates to #build_object_with_attributes' do
152
+ parser.should_receive(:build_object_with_attributes).with(content)
153
+ parser.send(:build_from_response)
154
+ end
155
+ end
156
+ end
157
+
158
+ context 'when there is no content' do
159
+ before do
160
+ parser.stub(:content).and_return(nil)
161
+ end
162
+
163
+ it 'returns nil' do
164
+ parser.send(:build_from_response).should be_nil
165
+ end
166
+ end
167
+ end
168
+
169
+ describe '#raise_not_found' do
170
+ context 'when the metadata hash contains :ids' do
171
+ let(:metadata) { { :ids => [1,2,3] } }
172
+
173
+ it 'raises a ResourceNotFound exception with the appropriate message' do
174
+ lambda { parser.send(:raise_not_found) }.should raise_error(Morpheus::ResourceNotFound, "Couldn't find all Dogs with IDs (1, 2, 3)")
175
+ end
176
+ end
177
+
178
+ context 'when the metadata hash contains :id' do
179
+ let(:metadata) { { :id => 1 } }
180
+
181
+ it 'raises a ResourceNotFound exception with the appropriate message' do
182
+ lambda { parser.send(:raise_not_found) }.should raise_error(Morpheus::ResourceNotFound, "Couldn't find Dog with ID=1")
183
+ end
184
+ end
185
+
186
+ context 'when the metadata hash does not contain either :ids or :id' do
187
+ it 'raises a ResourceNotFound exception with the appropriate message' do
188
+ lambda { parser.send(:raise_not_found) }.should raise_error(Morpheus::ResourceNotFound, /No resource was found at/)
189
+ end
190
+ end
191
+ end
192
+
193
+ describe '#parsed_body' do
194
+ it 'parses out the entire response body JSON' do
195
+ parser.send(:parsed_body).should eql({
196
+ 'content' => { 'foo' => 'bar' },
197
+ 'errors' => [{ 'foo' => 'cannot be "bar"' }]
198
+ })
199
+ end
200
+ end
201
+
202
+ describe '#content' do
203
+ it 'parses out the "content" attribute from the response body JSON' do
204
+ parser.send(:content).should eql({ 'foo' => 'bar' })
205
+ end
206
+ end
207
+
208
+ describe '#response_errors' do
209
+ it 'parses out the "errors" attribute from the response body JSON' do
210
+ parser.send(:response_errors).should eql([{ 'foo' => 'cannot be "bar"' }])
211
+ end
212
+ end
213
+
214
+ describe '#build_object_with_attributes' do
215
+ context 'when the attributes has a "type" key' do
216
+ let(:attributes) { { 'type' => 'Author', 'name' => 'Chuck Palahniuk' } }
217
+
218
+ it 'creates a new instance of the "type" with the attributes' do
219
+ Author.should_receive(:new).with(attributes)
220
+ parser.send(:build_object_with_attributes, attributes)
221
+ end
222
+ end
223
+
224
+ context 'when the attributes does not have a "type" key' do
225
+ let(:instance) { mock }
226
+ let(:attributes) { { 'name' => 'Fido' } }
227
+ it 'merges attributes into a new object of the owner class' do
228
+ Dog.should_receive(:new).and_return(instance)
229
+ instance.should_receive(:merge_attributes).with(attributes)
230
+ parser.send(:build_object_with_attributes, attributes)
231
+ end
232
+ end
15
233
  end
16
234
 
17
235
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: morpheus
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
4
+ hash: 3
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 3
9
- - 7
10
- version: 0.3.7
9
+ - 8
10
+ version: 0.3.8
11
11
  platform: ruby
12
12
  authors:
13
13
  - Ryan Moran
@@ -15,7 +15,8 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-01-17 00:00:00 Z
18
+ date: 2012-02-09 00:00:00 -08:00
19
+ default_executable:
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
21
22
  name: yajl-ruby
@@ -55,7 +56,7 @@ dependencies:
55
56
  requirement: &id003 !ruby/object:Gem::Requirement
56
57
  none: false
57
58
  requirements:
58
- - - ">"
59
+ - - ">="
59
60
  - !ruby/object:Gem::Version
60
61
  hash: 7
61
62
  segments:
@@ -71,7 +72,7 @@ dependencies:
71
72
  requirement: &id004 !ruby/object:Gem::Requirement
72
73
  none: false
73
74
  requirements:
74
- - - ">"
75
+ - - ">="
75
76
  - !ruby/object:Gem::Version
76
77
  hash: 7
77
78
  segments:
@@ -87,7 +88,7 @@ dependencies:
87
88
  requirement: &id005 !ruby/object:Gem::Requirement
88
89
  none: false
89
90
  requirements:
90
- - - ">"
91
+ - - ">="
91
92
  - !ruby/object:Gem::Version
92
93
  hash: 11
93
94
  segments:
@@ -103,7 +104,7 @@ dependencies:
103
104
  requirement: &id006 !ruby/object:Gem::Requirement
104
105
  none: false
105
106
  requirements:
106
- - - ">"
107
+ - - ">="
107
108
  - !ruby/object:Gem::Version
108
109
  hash: 7
109
110
  segments:
@@ -137,12 +138,12 @@ dependencies:
137
138
  requirements:
138
139
  - - ~>
139
140
  - !ruby/object:Gem::Version
140
- hash: 19
141
+ hash: 45
141
142
  segments:
142
143
  - 2
143
- - 7
144
- - 0
145
- version: 2.7.0
144
+ - 8
145
+ - 1
146
+ version: 2.8.1
146
147
  type: :development
147
148
  version_requirements: *id008
148
149
  - !ruby/object:Gem::Dependency
@@ -169,12 +170,12 @@ dependencies:
169
170
  requirements:
170
171
  - - ~>
171
172
  - !ruby/object:Gem::Version
172
- hash: 59
173
+ hash: 57
173
174
  segments:
174
175
  - 4
175
176
  - 5
176
- - 8
177
- version: 4.5.8
177
+ - 9
178
+ version: 4.5.9
178
179
  type: :development
179
180
  version_requirements: *id010
180
181
  description: RESTful API Client
@@ -190,7 +191,6 @@ files:
190
191
  - .autotest
191
192
  - .gitignore
192
193
  - .rspec
193
- - .rvmrc
194
194
  - Gemfile
195
195
  - LICENSE.txt
196
196
  - README.md
@@ -302,6 +302,7 @@ files:
302
302
  - spec/shared/active_model_lint_test.rb
303
303
  - spec/spec_helper.rb
304
304
  - spec/support/configuration.rb
305
+ has_rdoc: true
305
306
  homepage: ""
306
307
  licenses: []
307
308
 
@@ -331,7 +332,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
331
332
  requirements: []
332
333
 
333
334
  rubyforge_project:
334
- rubygems_version: 1.8.13
335
+ rubygems_version: 1.6.2
335
336
  signing_key:
336
337
  specification_version: 3
337
338
  summary: RESTful API Client
data/.rvmrc DELETED
@@ -1 +0,0 @@
1
- rvm use ree-1.8.7-2010.02@morpheus