morpheus 0.3.9 → 0.4.0

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/Gemfile CHANGED
@@ -3,6 +3,6 @@ source 'http://rubygems.org'
3
3
  gemspec
4
4
 
5
5
  group :development do
6
- gem 'simplecov', '~> 0.5.4'
6
+ gem 'simplecov', '~> 0.6.1'
7
7
  gem 'autotest-standalone', '~> 4.5.9'
8
8
  end
@@ -43,5 +43,13 @@ module Morpheus
43
43
  Typhoeus::Hydra.allow_net_connect?
44
44
  end
45
45
 
46
+ def parse_error_handler
47
+ @parse_error_handler
48
+ end
49
+
50
+ def parse_error_handler=(handler)
51
+ @parse_error_handler = handler
52
+ end
53
+
46
54
  end
47
55
  end
@@ -6,8 +6,8 @@ module Morpheus
6
6
  # Occurs when a request from a remote host is made while Morpheus::Configuration.allow_net_connect is set to false.
7
7
  class NetConnectNotAllowedError < ::StandardError
8
8
  attr_accessor :request
9
- def initialize(_request=nil)
10
- self.request= _request
9
+ def initialize(request = nil)
10
+ self.request= request
11
11
  end
12
12
  end
13
13
 
@@ -26,6 +26,10 @@ module Morpheus
26
26
  end
27
27
  end
28
28
 
29
+ def scoped
30
+ Relation.new(self)
31
+ end
32
+
29
33
  def all
30
34
  attributes = [UrlBuilder.find_all(self), nil, {}]
31
35
  get(*attributes)
@@ -12,16 +12,5 @@ module Morpheus
12
12
  end
13
13
 
14
14
  end
15
-
16
- def build_from_response(response)
17
- content = Yajl::Parser.parse(response.body)['content']
18
- if content.keys.include?('type')
19
- content['type'].constantize.new.merge_attributes(content)
20
- else
21
- merge_attributes(content)
22
- end
23
- end
24
- private :build_from_response
25
-
26
15
  end
27
16
  end
@@ -1,17 +1,13 @@
1
1
  module Morpheus
2
2
  class Reflection
3
- attr_reader :macro, :name, :options
3
+ attr_reader :macro, :name, :options, :class_name, :klass
4
4
 
5
5
  def initialize(macro, name, options = {})
6
- @macro, @name, @options = macro, name, options
7
- end
8
-
9
- def klass
10
- @klass ||= class_name.constantize
11
- end
12
-
13
- def class_name
14
- (options[:class_name] || name).to_s.singularize.camelize
6
+ @macro = macro
7
+ @name = name
8
+ @options = options
9
+ @class_name = (@options[:class_name] || @name).to_s.singularize.camelize
10
+ @klass = @class_name.constantize
15
11
  end
16
12
 
17
13
  def build_association(*options)
@@ -1,6 +1,10 @@
1
1
  module Morpheus
2
2
  class Relation < ActiveSupport::BasicObject
3
3
 
4
+ def class
5
+ ::Morpheus::Relation
6
+ end
7
+
4
8
  def initialize(owner)
5
9
  @owner = owner
6
10
  @target = nil
@@ -3,38 +3,55 @@ module Morpheus
3
3
  attr_reader :path, :params, :method
4
4
 
5
5
  def initialize(path, options = {})
6
- if options[:method] == :put
6
+ if options[:method] == :put
7
7
  options[:method] = :post
8
8
  options[:params].merge!(:_method => :put)
9
- end
9
+ end
10
10
 
11
- options[:username] = Configuration.username if Configuration.username
12
- options[:password] = Configuration.password if Configuration.password
11
+ if options[:params]
12
+ options[:params] = fix_array_param_keys(options[:params])
13
+ end
13
14
 
14
- super(Configuration.host + path, options)
15
+
16
+ options[:username] = Configuration.username if Configuration.username
17
+ options[:password] = Configuration.password if Configuration.password
18
+
19
+ super(Configuration.host + path, options)
20
+ end
21
+
22
+ def fix_array_param_keys(params)
23
+ fixed_params = {}
24
+ params.each do |key, value|
25
+ if Array === value
26
+ fixed_params.store("#{key}[]", value)
27
+ else
28
+ fixed_params.store(key, value)
29
+ end
30
+ end
31
+ fixed_params
15
32
  end
16
33
 
17
34
  def cache_key
18
- Digest::SHA1.hexdigest([method, url, params].inspect)
35
+ Digest::SHA1.hexdigest([method, url, params].inspect)
19
36
  end
20
37
 
21
38
  def response=(response)
22
- RequestCache.cache[cache_key] = response
23
- response.tag_for_caching!
24
- super
39
+ RequestCache.cache[cache_key] = response
40
+ response.tag_for_caching!
41
+ super
25
42
  end
26
43
 
27
44
  def response
28
- RequestQueue.run! if RequestQueue.has_request?(self)
29
- RequestCache.cache[cache_key]|| super
45
+ RequestQueue.run! if RequestQueue.has_request?(self)
46
+ RequestCache.cache[cache_key] || super
30
47
  end
31
48
 
32
49
  def self.enqueue(method, path, params)
33
- options = { :method => method }
34
- options.merge!(:params => params) unless params.blank?
35
- new(path, options).tap do |request|
50
+ options = { :method => method }
51
+ options.merge!(:params => params) unless params.blank?
52
+ new(path, options).tap do |request|
36
53
  RequestQueue.enqueue(request)
37
- end
54
+ end
38
55
  end
39
56
 
40
57
  end
@@ -70,7 +70,17 @@ module Morpheus
70
70
  end
71
71
 
72
72
  def parsed_body
73
- @parsed_body ||= Yajl::Parser.parse(@response.body)
73
+ @parsed_body ||= parse_body(@response.body)
74
+ end
75
+
76
+ def parse_body(body)
77
+ Yajl::Parser.parse(body)
78
+ rescue Yajl::ParseError
79
+ if Configuration.parse_error_handler
80
+ Configuration.parse_error_handler.handle(body)
81
+ else
82
+ raise
83
+ end
74
84
  end
75
85
 
76
86
  def content
@@ -1,3 +1,3 @@
1
1
  module Morpheus
2
- VERSION = '0.3.9'
2
+ VERSION = '0.4.0'
3
3
  end
data/morpheus.gemspec CHANGED
@@ -16,13 +16,13 @@ Gem::Specification.new do |gem|
16
16
  gem.require_paths = ['lib']
17
17
  gem.version = Morpheus::VERSION
18
18
 
19
- gem.add_dependency 'yajl-ruby', '~> 0.8.2'
20
- gem.add_dependency 'typhoeus', '~> 0.2.4'
19
+ gem.add_dependency 'yajl-ruby', '~> 1.1.0'
20
+ gem.add_dependency 'typhoeus', '~> 0.3.3'
21
21
  gem.add_dependency 'activemodel', '>= 3.0.0'
22
22
  gem.add_dependency 'activesupport', '>= 3.0.0'
23
23
  gem.add_dependency 'i18n', '>= 0.5.0'
24
24
 
25
25
  gem.add_development_dependency 'rails', '>= 3.0.0'
26
26
  gem.add_development_dependency 'sqlite3', '~> 1.3.3'
27
- gem.add_development_dependency 'rspec-rails', '~> 2.8.1'
27
+ gem.add_development_dependency 'rspec-rails', '~> 2.9.0'
28
28
  end
@@ -112,4 +112,15 @@ describe Morpheus::Configuration do
112
112
  end
113
113
  end
114
114
 
115
+ describe '#parse_error_handler' do
116
+ let(:handler) { mock }
117
+
118
+ before { Morpheus::Configuration.parse_error_handler = handler }
119
+ after { Morpheus::Configuration.parse_error_handler = nil }
120
+
121
+ it 'allows a Yajl::ParseError handler class to be set' do
122
+ Morpheus::Configuration.parse_error_handler.should eql(handler)
123
+ end
124
+ end
125
+
115
126
  end
@@ -1,6 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Morpheus::Attributes do
4
+ let(:book) { Book.new }
4
5
 
5
6
  describe '.property' do
6
7
  it 'defines setter and getter methods for the given property' do
@@ -57,7 +58,9 @@ describe Morpheus::Attributes do
57
58
  end
58
59
 
59
60
  describe '#update_reflection' do
60
- pending
61
+ it 'returns a hash containing all keys except :id, :errors, :valid, and any keys matching a reflection' do
62
+ book.attributes_without_basic_attributes.should eql(HashWithIndifferentAccess.new(:title => nil, :author_id => nil))
63
+ end
61
64
  end
62
65
 
63
66
  describe '#merge_attributes' do
@@ -1,13 +1,26 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Morpheus::Filtering do
4
+ let(:klass) do
5
+ Class.new do
6
+ include Morpheus::Filtering
7
+ end
8
+ end
9
+ let(:name) { mock }
10
+ let(:block) { lambda { |sentinel| sentinel } }
4
11
 
5
12
  describe '.filter' do
6
- pending
13
+ it 'stores the given filter into the filter list for this class' do
14
+ klass.filter(name, &block)
15
+ klass.find_filter(name).call(:sentinel).should eql(:sentinel)
16
+ end
7
17
  end
8
18
 
9
19
  describe '.find_filter' do
10
- pending
20
+ it 'retrieves a Filter object matching the given name argument' do
21
+ klass.filter(name, &block)
22
+ klass.find_filter(name).call(:sentinel).should eql(:sentinel)
23
+ end
11
24
  end
12
25
 
13
26
  end
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  describe Morpheus::Finders do
4
4
 
5
- describe '#find' do
5
+ describe '.find' do
6
6
  context 'when the argument is a single integer' do
7
7
  context 'when this record exists on the external service' do
8
8
  before(:each) do
@@ -110,7 +110,13 @@ describe Morpheus::Finders do
110
110
  end
111
111
  end
112
112
 
113
- describe '#all' do
113
+ describe '.scoped' do
114
+ it 'returns a Relation wrapping this class' do
115
+ Dog.scoped.class.should eql(Morpheus::Relation)
116
+ end
117
+ end
118
+
119
+ describe '.all' do
114
120
  before(:each) do
115
121
  @dogs = [
116
122
  Dog.new(:id => 1, :name => 'Daisy', :breed => 'English Bulldog'),
@@ -130,7 +136,7 @@ describe Morpheus::Finders do
130
136
  end
131
137
  end
132
138
 
133
- describe '#first' do
139
+ describe '.first' do
134
140
  before(:each) do
135
141
  @dogs = [Dog.new(:id => 1, :name => 'Daisy', :breed => 'English Bulldog')]
136
142
  Dog.stub(:get).and_return(@dogs)
@@ -142,7 +148,7 @@ describe Morpheus::Finders do
142
148
  end
143
149
  end
144
150
 
145
- describe '#where' do
151
+ describe '.where' do
146
152
  context 'when the where attribute is an acceptable attribute' do
147
153
  context 'for a where clause with one attribute' do
148
154
  before(:each) do
@@ -168,7 +174,7 @@ describe Morpheus::Finders do
168
174
  end
169
175
  end
170
176
 
171
- describe '#limit' do
177
+ describe '.limit' do
172
178
  before(:each) do
173
179
  @dogs = [
174
180
  Dog.new(:id => 1, :name => 'Daisy', :breed => 'English Bulldog'),
@@ -183,7 +189,7 @@ describe Morpheus::Finders do
183
189
  end
184
190
  end
185
191
 
186
- describe '#page' do
192
+ describe '.page' do
187
193
  before(:each) do
188
194
  Dog.results_per_page = 10
189
195
  @dogs = [
@@ -199,7 +205,7 @@ describe Morpheus::Finders do
199
205
  end
200
206
  end
201
207
 
202
- describe '#results_per_page' do
208
+ describe '.results_per_page' do
203
209
  it 'defaults to 10' do
204
210
  Dog.results_per_page.should eql(10)
205
211
  end
@@ -154,15 +154,51 @@ describe Morpheus::Persistence do
154
154
  end
155
155
 
156
156
  describe '#destroy' do
157
- pending
157
+ it 'delegates to .delete' do
158
+ State.should_receive(:delete).with('/states/1')
159
+ state = State.new(:id => 1)
160
+ state.destroy
161
+ end
158
162
  end
159
163
 
160
164
  describe '.create' do
161
- pending
165
+ let(:params) { mock }
166
+ let!(:state) { State.new }
167
+
168
+ before do
169
+ State.stub(:new).and_return(state)
170
+ state.stub(:save)
171
+ end
172
+
173
+ it 'instantiates a new record' do
174
+ State.should_receive(:new).with(params).and_return(state)
175
+ State.create(params)
176
+ end
177
+
178
+ it 'saves the newly instantiated record' do
179
+ state.should_receive(:save)
180
+ State.create(params)
181
+ end
162
182
  end
163
183
 
164
184
  describe '.create!' do
165
- pending
185
+ let(:params) { mock }
186
+ let!(:state) { State.new }
187
+
188
+ before do
189
+ State.stub(:new).and_return(state)
190
+ state.stub(:save)
191
+ end
192
+
193
+ it 'instantiates a new record' do
194
+ State.should_receive(:new).with(params).and_return(state)
195
+ State.create(params)
196
+ end
197
+
198
+ it 'saves the newly instantiated record' do
199
+ state.should_receive(:save)
200
+ State.create(params)
201
+ end
166
202
  end
167
203
 
168
204
  end
@@ -1,21 +1,96 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Morpheus::RequestHandling do
4
+ let(:path) { mock }
5
+ let(:params) { mock }
6
+ let(:metadata) { mock }
7
+ let(:request) { mock }
8
+ let(:block) { lambda {} }
9
+ let(:klass) do
10
+ Class.new do
11
+ include Morpheus::RequestHandling
12
+ end
13
+ end
14
+
15
+ before do
16
+ Morpheus::Request.stub(:enqueue) { request }
17
+ klass.stub(:response_from_request)
18
+ end
4
19
 
5
20
  describe '.get' do
6
- pending
21
+ it 'enqueues a request' do
22
+ Morpheus::Request.should_receive(:enqueue).with(:get, path, params)
23
+ klass.get(path, params, metadata)
24
+ end
25
+
26
+ it 'delegates to .response_from_request' do
27
+ klass.should_receive(:response_from_request).with(request, metadata)
28
+ klass.get(path, params, metadata)
29
+ end
30
+
31
+ context 'when a block is given' do
32
+ it 'stores the block on the request to be called on completion' do
33
+ request.should_receive(:on_complete=).with(block)
34
+ klass.get(path, params, metadata, &block)
35
+ end
36
+ end
7
37
  end
8
38
 
9
39
  describe '.post' do
10
- pending
40
+ it 'enqueues a request' do
41
+ Morpheus::Request.should_receive(:enqueue).with(:post, path, params)
42
+ klass.post(path, params, metadata)
43
+ end
44
+
45
+ it 'delegates to .response_from_request' do
46
+ klass.should_receive(:response_from_request).with(request, metadata)
47
+ klass.put(path, params, metadata)
48
+ end
49
+
50
+ context 'when a block is given' do
51
+ it 'stores the block on the request to be called on completion' do
52
+ request.should_receive(:on_complete=).with(block)
53
+ klass.post(path, params, metadata, &block)
54
+ end
55
+ end
11
56
  end
12
57
 
13
58
  describe '.put' do
14
- pending
59
+ it 'enqueues a request' do
60
+ Morpheus::Request.should_receive(:enqueue).with(:put, path, params)
61
+ klass.put(path, params, metadata)
62
+ end
63
+
64
+ it 'delegates to .response_from_request' do
65
+ klass.should_receive(:response_from_request).with(request, metadata)
66
+ klass.put(path, params, metadata)
67
+ end
68
+
69
+ context 'when a block is given' do
70
+ it 'stores the block on the request to be called on completion' do
71
+ request.should_receive(:on_complete=).with(block)
72
+ klass.put(path, params, metadata, &block)
73
+ end
74
+ end
15
75
  end
16
76
 
17
77
  describe '.delete' do
18
- pending
78
+ it 'enqueues a request' do
79
+ Morpheus::Request.should_receive(:enqueue).with(:delete, path, params)
80
+ klass.delete(path, params, metadata)
81
+ end
82
+
83
+ it 'delegates to .response_from_request' do
84
+ klass.should_receive(:response_from_request).with(request, metadata)
85
+ klass.delete(path, params, metadata)
86
+ end
87
+
88
+ context 'when a block is given' do
89
+ it 'stores the block on the request to be called on completion' do
90
+ request.should_receive(:on_complete=).with(block)
91
+ klass.delete(path, params, metadata, &block)
92
+ end
93
+ end
19
94
  end
20
95
 
21
96
  end
@@ -1,13 +1,19 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Morpheus::ResponseParsing do
4
-
5
- describe '.response_from_request' do
6
- pending
4
+ let(:model) do
5
+ Class.new do
6
+ include Morpheus::ResponseParsing
7
+ end
7
8
  end
9
+ let(:request) { mock }
10
+ let(:metadata) { mock }
8
11
 
9
- describe '#build_from_response' do
10
- pending
12
+ describe '.response_from_request' do
13
+ it 'delegates to ResponseParser to build a parsed response from a request' do
14
+ Morpheus::ResponseParser.should_receive(:parse).with(model, request, metadata)
15
+ model.response_from_request(request, metadata)
16
+ end
11
17
  end
12
18
 
13
19
  end
@@ -1,29 +1,96 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Morpheus::UrlSupport do
4
+ let(:model) do
5
+ Class.new do
6
+ include Morpheus::UrlSupport
7
+
8
+ def self.model_name
9
+ 'OriginalModelName'
10
+ end
11
+ end
12
+ end
4
13
 
5
14
  describe '.url_name' do
6
- pending
15
+ context 'when @url_name has been set' do
16
+ before do
17
+ model.instance_variable_set('@url_name', :sentinel)
18
+ end
19
+
20
+ it 'returns the value of @url_name' do
21
+ model.url_name.should eql(:sentinel)
22
+ end
23
+ end
24
+
25
+ context 'when @url_name has not been set' do
26
+ it 'returns an underscored version of the return value of .model_name' do
27
+ model.url_name.should eql('original_model_name')
28
+ end
29
+ end
30
+ end
31
+
32
+ describe '.singular_url_name' do
33
+ context 'when @url_name has been set' do
34
+ before do
35
+ model.instance_variable_set('@url_name', :sentinel)
36
+ end
37
+
38
+ it 'returns the value of @url_name' do
39
+ model.singular_url_name.should eql(:sentinel)
40
+ end
41
+ end
42
+
43
+ context 'when @url_name has not been set' do
44
+ it 'returns an underscored version of the return value of .model_name' do
45
+ model.singular_url_name.should eql('original_model_name')
46
+ end
47
+ end
7
48
  end
8
49
 
9
50
  describe '.plural_url_name' do
10
- pending
51
+ it 'returns a pluralized version of the return value of .url_name' do
52
+ model.plural_url_name.should eql('original_model_names')
53
+ end
11
54
  end
12
55
 
13
56
  describe '.set_base_url' do
14
- pending
57
+ it 'allows @url_name to be set with the given value' do
58
+ model.set_base_url(:sentinel)
59
+ model.instance_variable_get('@url_name').should eql(:sentinel)
60
+ end
15
61
  end
16
62
 
17
63
  describe '.attributes_root' do
18
- pending
64
+ context 'when @attributes_root has been set' do
65
+ before do
66
+ model.instance_variable_set('@attributes_root', :sentinel)
67
+ end
68
+
69
+ it 'returns the value of @attributes_root' do
70
+ model.attributes_root.should eql(:sentinel)
71
+ end
72
+ end
73
+
74
+ context 'when @attributes_root has not been set' do
75
+ it 'returns an underscored version of the return value of .model_name' do
76
+ model.attributes_root.should eql('original_model_name')
77
+ end
78
+ end
19
79
  end
20
80
 
21
81
  describe '.set_attributes_root' do
22
- pending
82
+ it 'allows @attributes_root to be set with the given value' do
83
+ model.set_attributes_root(:sentinel)
84
+ model.instance_variable_get('@attributes_root').should eql(:sentinel)
85
+ end
23
86
  end
24
87
 
25
88
  describe 'set_base_model_name' do
26
- pending
89
+ it 'allows @url_name and @attributes_root to be set at the same time, with the same value' do
90
+ model.set_base_model_name(:sentinel)
91
+ model.instance_variable_get('@url_name').should eql(:sentinel)
92
+ model.instance_variable_get('@attributes_root').should eql(:sentinel)
93
+ end
27
94
  end
28
95
 
29
96
  end
@@ -1,21 +1,59 @@
1
1
  require 'spec_helper'
2
2
 
3
+ AccountHolder = Class.new
4
+
3
5
  describe Morpheus::Reflection do
6
+ let(:macro) { mock }
7
+ let(:name) { 'account_holders' }
8
+ let(:options) { Hash.new }
9
+ let(:reflection) { Morpheus::Reflection.new(macro, name, options) }
10
+ let(:parameters) { mock }
4
11
 
5
- describe '#initialize' do
6
- pending
12
+ describe '#macro' do
13
+ it 'returns the value passed in for macro' do
14
+ reflection.macro.should eql(macro)
15
+ end
7
16
  end
8
17
 
9
- describe '#klass' do
10
- pending
18
+ describe '#name' do
19
+ it 'returns the value passed in for name' do
20
+ reflection.name.should eql(name)
21
+ end
22
+ end
23
+
24
+ describe '#options' do
25
+ it 'returns the value passed in for options' do
26
+ reflection.options.should eql(options)
27
+ end
11
28
  end
12
29
 
13
30
  describe '#class_name' do
14
- pending
31
+ context 'when the :class_name option is given' do
32
+ let(:options) { { :class_name => 'account_holders' } }
33
+
34
+ it 'returns a singularized and camelized version of that option' do
35
+ reflection.class_name.should eql('AccountHolder')
36
+ end
37
+ end
38
+
39
+ context 'when the :class_name option is not given' do
40
+ it 'returns a singularized and camelized version of the name parameter' do
41
+ reflection.class_name.should eql('AccountHolder')
42
+ end
43
+ end
44
+ end
45
+
46
+ describe '#klass' do
47
+ it 'returns a constantized version of the return value of #class_name' do
48
+ reflection.klass.should eql(AccountHolder)
49
+ end
15
50
  end
16
51
 
17
52
  describe '#build_association' do
18
- pending
53
+ it 'initializes a new object of the #klass type with the given parameters' do
54
+ AccountHolder.should_receive(:new).with(parameters)
55
+ reflection.build_association(parameters)
56
+ end
19
57
  end
20
58
 
21
59
  end
@@ -1,18 +1,25 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Morpheus::Relation do
4
+ let(:relation) { Dog.scoped }
5
+
6
+ describe '.class' do
7
+ it 'returns Morpheus::Relation' do
8
+ relation.class.should eql(Morpheus::Relation)
9
+ end
10
+ end
4
11
 
5
12
  describe '#where' do
6
13
  it 'makes a request to find all of the given records, with the where parameters' do
7
14
  Dog.should_receive(:get).with('/dogs', { :name => 'Daisy', :breed => 'English Bulldog' })
8
- Dog.where(:name => 'Daisy', :breed => 'English Bulldog').all
15
+ relation.where(:name => 'Daisy', :breed => 'English Bulldog').all
9
16
  end
10
17
  end
11
18
 
12
19
  describe '#limit' do
13
20
  it 'makes a request to find all of the given records, with the limit parameter' do
14
21
  Dog.should_receive(:get).with('/dogs', { :limit => 2 })
15
- Dog.limit(2).all
22
+ relation.limit(2).all
16
23
  end
17
24
  end
18
25
 
@@ -20,27 +27,40 @@ describe Morpheus::Relation do
20
27
  it 'makes a request to find all of the given records, with the chained parameters' do
21
28
  Dog.results_per_page = 10
22
29
  Dog.should_receive(:get).with('/dogs', { :limit => 10, :offset => 20 })
23
- Dog.page(3).all
30
+ relation.page(3).all
24
31
  end
25
32
  end
26
33
 
27
34
  describe '#all' do
28
- pending
35
+ it 'makes a request to find all of the given records, with any of the chained parameters' do
36
+ Dog.should_receive(:get).with('/dogs')
37
+ relation.all
38
+ end
29
39
  end
30
40
 
31
41
  describe '#to_a' do
32
- pending
42
+ it 'makes a request to find all of the given records, with any of the chained parameters' do
43
+ Dog.should_receive(:get).with('/dogs')
44
+ relation.to_a
45
+ end
33
46
  end
34
47
 
35
48
  describe '#to_json' do
36
- pending
49
+ let(:sentinel) { Object.new }
50
+ let(:args) { [1, 2, 3] }
51
+
52
+ it 'calls #to_json on the return value of to_a' do
53
+ Dog.stub(:get) { sentinel }
54
+ sentinel.should_receive(:to_json).with(*args)
55
+ relation.to_json(*args)
56
+ end
37
57
  end
38
58
 
39
59
  describe 'chaining relations' do
40
60
  it 'makes a request to find all of the given records, with the chained parameters' do
41
61
  Dog.results_per_page = 10
42
62
  Dog.should_receive(:get).with('/dogs', { :name => 'Daisy', :breed => 'English Bulldog', :limit => 2, :offset => 20 })
43
- Dog.where(:name => 'Daisy', :breed => 'English Bulldog').page(3).limit(2).all
63
+ relation.where(:name => 'Daisy', :breed => 'English Bulldog').page(3).limit(2).all
44
64
  end
45
65
  end
46
66
 
@@ -1,13 +1,19 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Morpheus::Request do
4
- let(:request) do
5
- Morpheus::Request.new('/path', :method => :get, :params => { :one => 1 })
6
- end
4
+ let(:request) { Morpheus::Request.new('/path', :method => :get, :params => { :one => 1 }) }
7
5
  let(:response) { Morpheus::Response.new }
8
6
 
9
- describe '#initialize' do
10
- pending
7
+ describe '#fix_array_param_keys' do
8
+ it 'changes the param keys for params with array values to match what Typhoeus expects' do
9
+ request = Morpheus::Request.new('/dogs', :params => { :ids => [1,2,3] })
10
+ request.params.should eql({ 'ids[]' => [1,2,3] })
11
+ end
12
+
13
+ it 'does no param key fixing if there are no params' do
14
+ request = Morpheus::Request.new('/dogs')
15
+ request.params.should be_nil
16
+ end
11
17
  end
12
18
 
13
19
  describe '#cache_key' do
@@ -72,7 +78,22 @@ describe Morpheus::Request do
72
78
  end
73
79
 
74
80
  context 'when the RequestCache does not have a cached response for this request' do
75
- pending
81
+ module RequestSentinel
82
+ def response
83
+ response_super_call_sentinel
84
+ super
85
+ end
86
+
87
+ def response_super_call_sentinel
88
+ end
89
+ end
90
+
91
+ before { Morpheus::Request.send(:include, RequestSentinel) }
92
+
93
+ it 'delegates to super' do
94
+ request.should_receive(:response_super_call_sentinel)
95
+ request.response
96
+ end
76
97
  end
77
98
  end
78
99
 
@@ -199,6 +199,31 @@ describe Morpheus::ResponseParser do
199
199
  end
200
200
  end
201
201
 
202
+ describe '#parse_body' do
203
+ before { Yajl::Parser.stub(:parse).and_raise(Yajl::ParseError) }
204
+
205
+ context 'when there is no configured parse error handler' do
206
+ it 'reraises the Yajl::ParseError exception' do
207
+ lambda {
208
+ parser.send(:parse_body, 'some string')
209
+ }.should raise_error(Yajl::ParseError)
210
+ end
211
+ end
212
+
213
+ context 'when there is a configured parse error handler' do
214
+ let(:offending_string) { 'offending string' }
215
+
216
+ module Handler; end
217
+
218
+ before { Morpheus::Configuration.parse_error_handler = Handler }
219
+
220
+ it 'calls #handle on a handler instance, passing the offending string' do
221
+ Handler.should_receive(:handle).with(offending_string)
222
+ parser.send(:parse_body, offending_string)
223
+ end
224
+ end
225
+ end
226
+
202
227
  describe '#content' do
203
228
  it 'parses out the "content" attribute from the response body JSON' do
204
229
  parser.send(:content).should eql({ 'foo' => 'bar' })
metadata CHANGED
@@ -1,161 +1,111 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: morpheus
3
- version: !ruby/object:Gem::Version
4
- hash: 1
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.0
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 3
9
- - 9
10
- version: 0.3.9
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Ryan Moran
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2012-02-22 00:00:00 -08:00
19
- default_executable:
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
12
+ date: 2012-03-18 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
22
15
  name: yajl-ruby
23
- prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: &70093023811320 !ruby/object:Gem::Requirement
25
17
  none: false
26
- requirements:
18
+ requirements:
27
19
  - - ~>
28
- - !ruby/object:Gem::Version
29
- hash: 59
30
- segments:
31
- - 0
32
- - 8
33
- - 2
34
- version: 0.8.2
20
+ - !ruby/object:Gem::Version
21
+ version: 1.1.0
35
22
  type: :runtime
36
- version_requirements: *id001
37
- - !ruby/object:Gem::Dependency
38
- name: typhoeus
39
23
  prerelease: false
40
- requirement: &id002 !ruby/object:Gem::Requirement
24
+ version_requirements: *70093023811320
25
+ - !ruby/object:Gem::Dependency
26
+ name: typhoeus
27
+ requirement: &70093023810620 !ruby/object:Gem::Requirement
41
28
  none: false
42
- requirements:
29
+ requirements:
43
30
  - - ~>
44
- - !ruby/object:Gem::Version
45
- hash: 31
46
- segments:
47
- - 0
48
- - 2
49
- - 4
50
- version: 0.2.4
31
+ - !ruby/object:Gem::Version
32
+ version: 0.3.3
51
33
  type: :runtime
52
- version_requirements: *id002
53
- - !ruby/object:Gem::Dependency
54
- name: activemodel
55
34
  prerelease: false
56
- requirement: &id003 !ruby/object:Gem::Requirement
35
+ version_requirements: *70093023810620
36
+ - !ruby/object:Gem::Dependency
37
+ name: activemodel
38
+ requirement: &70093023810160 !ruby/object:Gem::Requirement
57
39
  none: false
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- hash: 7
62
- segments:
63
- - 3
64
- - 0
65
- - 0
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
66
43
  version: 3.0.0
67
44
  type: :runtime
68
- version_requirements: *id003
69
- - !ruby/object:Gem::Dependency
70
- name: activesupport
71
45
  prerelease: false
72
- requirement: &id004 !ruby/object:Gem::Requirement
46
+ version_requirements: *70093023810160
47
+ - !ruby/object:Gem::Dependency
48
+ name: activesupport
49
+ requirement: &70093023809700 !ruby/object:Gem::Requirement
73
50
  none: false
74
- requirements:
75
- - - ">="
76
- - !ruby/object:Gem::Version
77
- hash: 7
78
- segments:
79
- - 3
80
- - 0
81
- - 0
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
82
54
  version: 3.0.0
83
55
  type: :runtime
84
- version_requirements: *id004
85
- - !ruby/object:Gem::Dependency
86
- name: i18n
87
56
  prerelease: false
88
- requirement: &id005 !ruby/object:Gem::Requirement
57
+ version_requirements: *70093023809700
58
+ - !ruby/object:Gem::Dependency
59
+ name: i18n
60
+ requirement: &70093023809200 !ruby/object:Gem::Requirement
89
61
  none: false
90
- requirements:
91
- - - ">="
92
- - !ruby/object:Gem::Version
93
- hash: 11
94
- segments:
95
- - 0
96
- - 5
97
- - 0
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
98
65
  version: 0.5.0
99
66
  type: :runtime
100
- version_requirements: *id005
101
- - !ruby/object:Gem::Dependency
102
- name: rails
103
67
  prerelease: false
104
- requirement: &id006 !ruby/object:Gem::Requirement
68
+ version_requirements: *70093023809200
69
+ - !ruby/object:Gem::Dependency
70
+ name: rails
71
+ requirement: &70093023808740 !ruby/object:Gem::Requirement
105
72
  none: false
106
- requirements:
107
- - - ">="
108
- - !ruby/object:Gem::Version
109
- hash: 7
110
- segments:
111
- - 3
112
- - 0
113
- - 0
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
114
76
  version: 3.0.0
115
77
  type: :development
116
- version_requirements: *id006
117
- - !ruby/object:Gem::Dependency
118
- name: sqlite3
119
78
  prerelease: false
120
- requirement: &id007 !ruby/object:Gem::Requirement
79
+ version_requirements: *70093023808740
80
+ - !ruby/object:Gem::Dependency
81
+ name: sqlite3
82
+ requirement: &70093023808260 !ruby/object:Gem::Requirement
121
83
  none: false
122
- requirements:
84
+ requirements:
123
85
  - - ~>
124
- - !ruby/object:Gem::Version
125
- hash: 29
126
- segments:
127
- - 1
128
- - 3
129
- - 3
86
+ - !ruby/object:Gem::Version
130
87
  version: 1.3.3
131
88
  type: :development
132
- version_requirements: *id007
133
- - !ruby/object:Gem::Dependency
134
- name: rspec-rails
135
89
  prerelease: false
136
- requirement: &id008 !ruby/object:Gem::Requirement
90
+ version_requirements: *70093023808260
91
+ - !ruby/object:Gem::Dependency
92
+ name: rspec-rails
93
+ requirement: &70093023807800 !ruby/object:Gem::Requirement
137
94
  none: false
138
- requirements:
95
+ requirements:
139
96
  - - ~>
140
- - !ruby/object:Gem::Version
141
- hash: 45
142
- segments:
143
- - 2
144
- - 8
145
- - 1
146
- version: 2.8.1
97
+ - !ruby/object:Gem::Version
98
+ version: 2.9.0
147
99
  type: :development
148
- version_requirements: *id008
100
+ prerelease: false
101
+ version_requirements: *70093023807800
149
102
  description: RESTful API Client
150
- email:
103
+ email:
151
104
  - ryan.moran@revolutionprep.com
152
105
  executables: []
153
-
154
106
  extensions: []
155
-
156
107
  extra_rdoc_files: []
157
-
158
- files:
108
+ files:
159
109
  - .autotest
160
110
  - .gitignore
161
111
  - .rspec
@@ -271,41 +221,31 @@ files:
271
221
  - spec/shared/active_model_lint_test.rb
272
222
  - spec/spec_helper.rb
273
223
  - spec/support/configuration.rb
274
- has_rdoc: true
275
- homepage: ""
224
+ homepage: ''
276
225
  licenses: []
277
-
278
226
  post_install_message:
279
227
  rdoc_options: []
280
-
281
- require_paths:
228
+ require_paths:
282
229
  - lib
283
- required_ruby_version: !ruby/object:Gem::Requirement
230
+ required_ruby_version: !ruby/object:Gem::Requirement
284
231
  none: false
285
- requirements:
286
- - - ">="
287
- - !ruby/object:Gem::Version
288
- hash: 3
289
- segments:
290
- - 0
291
- version: "0"
292
- required_rubygems_version: !ruby/object:Gem::Requirement
232
+ requirements:
233
+ - - ! '>='
234
+ - !ruby/object:Gem::Version
235
+ version: '0'
236
+ required_rubygems_version: !ruby/object:Gem::Requirement
293
237
  none: false
294
- requirements:
295
- - - ">="
296
- - !ruby/object:Gem::Version
297
- hash: 3
298
- segments:
299
- - 0
300
- version: "0"
238
+ requirements:
239
+ - - ! '>='
240
+ - !ruby/object:Gem::Version
241
+ version: '0'
301
242
  requirements: []
302
-
303
243
  rubyforge_project:
304
- rubygems_version: 1.6.2
244
+ rubygems_version: 1.8.15
305
245
  signing_key:
306
246
  specification_version: 3
307
247
  summary: RESTful API Client
308
- test_files:
248
+ test_files:
309
249
  - spec/dummy/Rakefile
310
250
  - spec/dummy/app/controllers/application_controller.rb
311
251
  - spec/dummy/app/helpers/application_helper.rb