morpheus 0.3.7 → 0.3.8

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.
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