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