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 +1 -1
- data/lib/morpheus/configuration.rb +8 -0
- data/lib/morpheus/errors.rb +2 -2
- data/lib/morpheus/mixins/finders.rb +4 -0
- data/lib/morpheus/mixins/response_parsing.rb +0 -11
- data/lib/morpheus/reflection.rb +6 -10
- data/lib/morpheus/relation.rb +4 -0
- data/lib/morpheus/request.rb +32 -15
- data/lib/morpheus/response_parser.rb +11 -1
- data/lib/morpheus/version.rb +1 -1
- data/morpheus.gemspec +3 -3
- data/spec/morpheus/configuration_spec.rb +11 -0
- data/spec/morpheus/mixins/attributes_spec.rb +4 -1
- data/spec/morpheus/mixins/filtering_spec.rb +15 -2
- data/spec/morpheus/mixins/finders_spec.rb +13 -7
- data/spec/morpheus/mixins/persistence_spec.rb +39 -3
- data/spec/morpheus/mixins/request_handling_spec.rb +79 -4
- data/spec/morpheus/mixins/response_parsing_spec.rb +11 -5
- data/spec/morpheus/mixins/url_support_spec.rb +73 -6
- data/spec/morpheus/reflection_spec.rb +44 -6
- data/spec/morpheus/relation_spec.rb +27 -7
- data/spec/morpheus/request_spec.rb +27 -6
- data/spec/morpheus/response_parser_spec.rb +25 -0
- metadata +77 -137
data/Gemfile
CHANGED
data/lib/morpheus/errors.rb
CHANGED
@@ -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(
|
10
|
-
self.request=
|
9
|
+
def initialize(request = nil)
|
10
|
+
self.request= request
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
@@ -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
|
data/lib/morpheus/reflection.rb
CHANGED
@@ -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
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
@klass
|
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)
|
data/lib/morpheus/relation.rb
CHANGED
data/lib/morpheus/request.rb
CHANGED
@@ -3,38 +3,55 @@ module Morpheus
|
|
3
3
|
attr_reader :path, :params, :method
|
4
4
|
|
5
5
|
def initialize(path, options = {})
|
6
|
-
|
6
|
+
if options[:method] == :put
|
7
7
|
options[:method] = :post
|
8
8
|
options[:params].merge!(:_method => :put)
|
9
|
-
|
9
|
+
end
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
if options[:params]
|
12
|
+
options[:params] = fix_array_param_keys(options[:params])
|
13
|
+
end
|
13
14
|
|
14
|
-
|
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
|
-
|
35
|
+
Digest::SHA1.hexdigest([method, url, params].inspect)
|
19
36
|
end
|
20
37
|
|
21
38
|
def response=(response)
|
22
|
-
|
23
|
-
|
24
|
-
|
39
|
+
RequestCache.cache[cache_key] = response
|
40
|
+
response.tag_for_caching!
|
41
|
+
super
|
25
42
|
end
|
26
43
|
|
27
44
|
def response
|
28
|
-
|
29
|
-
|
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
|
-
|
34
|
-
|
35
|
-
|
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
|
-
|
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 ||=
|
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
|
data/lib/morpheus/version.rb
CHANGED
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', '~>
|
20
|
-
gem.add_dependency 'typhoeus', '~> 0.
|
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.
|
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
|
-
|
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
|
-
|
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
|
-
|
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 '
|
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 '
|
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 '
|
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 '
|
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 '
|
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 '
|
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 '
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
6
|
-
|
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 '
|
10
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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 '#
|
6
|
-
|
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 '#
|
10
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
30
|
+
relation.page(3).all
|
24
31
|
end
|
25
32
|
end
|
26
33
|
|
27
34
|
describe '#all' do
|
28
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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)
|
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 '#
|
10
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
19
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
289
|
-
|
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
|
-
|
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.
|
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
|