morpheus 0.3.9 → 0.4.0

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