lazy_resource 0.3.3 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +33 -2
- data/lazy_resource.gemspec +3 -3
- data/lib/lazy_resource/attributes.rb +1 -1
- data/lib/lazy_resource/ext/typhoeus.rb +6 -2
- data/lib/lazy_resource/http_mock.rb +1 -5
- data/lib/lazy_resource/mapping.rb +2 -1
- data/lib/lazy_resource/relation.rb +4 -4
- data/lib/lazy_resource/request.rb +3 -7
- data/lib/lazy_resource/version.rb +1 -1
- data/spec/lazy_resource/attributes_spec.rb +2 -2
- data/spec/lazy_resource/ext/typhoeus_spec.rb +6 -6
- data/spec/lazy_resource/lazy_resource_spec.rb +2 -1
- data/spec/lazy_resource/mapping_spec.rb +49 -10
- data/spec/lazy_resource/request_spec.rb +3 -25
- data/spec/lazy_resource/resource_spec.rb +0 -4
- metadata +8 -8
data/README.md
CHANGED
@@ -46,7 +46,6 @@ Or install it yourself as:
|
|
46
46
|
|
47
47
|
me = User.find(1) # => GET /users/1
|
48
48
|
bobs = User.where(:first_name => 'Bob') # => GET /users?first_name=Bob
|
49
|
-
sam = User.find_by_first_name('Sam') # => GET /users?first_name=Sam
|
50
49
|
terry = User.new(:first_name => 'Terry', :last_name => 'Simpson')
|
51
50
|
terry.save # => POST /users
|
52
51
|
terry.last_name = 'Jackson'
|
@@ -96,6 +95,39 @@ was saved. Pretty neat, eh?
|
|
96
95
|
Sure thing! Take a look at the files in the `examples` directory, or
|
97
96
|
read through the specs.
|
98
97
|
|
98
|
+
### How about a section of random features?
|
99
|
+
|
100
|
+
Here you go:
|
101
|
+
|
102
|
+
Fetch associations without hitting the URL generation code.
|
103
|
+
|
104
|
+
class Photo
|
105
|
+
include LazyResource::Resource
|
106
|
+
|
107
|
+
attribute :id, Fixnum
|
108
|
+
attribute :photographer_url, String
|
109
|
+
attribute :photographer, User, :using => :photographer_url
|
110
|
+
|
111
|
+
# or define it yourself
|
112
|
+
def photographer_url
|
113
|
+
"/path/to/photographer"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
Parsing responses like { 'photo': ... }
|
118
|
+
|
119
|
+
class Photo
|
120
|
+
include LazyResource::Resource
|
121
|
+
|
122
|
+
self.root_node_name = 'photo'
|
123
|
+
end
|
124
|
+
|
125
|
+
or multiple options
|
126
|
+
|
127
|
+
class Photo
|
128
|
+
self.root_node_name = ['photo', 'photos']
|
129
|
+
end
|
130
|
+
|
99
131
|
## Contributing
|
100
132
|
|
101
133
|
1. Fork it
|
@@ -129,5 +161,4 @@ Thanks to:
|
|
129
161
|
## TODO
|
130
162
|
|
131
163
|
* Clean up `LazyResource::Attributes#create_setter`
|
132
|
-
* Add more specs for associations
|
133
164
|
|
data/lazy_resource.gemspec
CHANGED
@@ -4,8 +4,8 @@ require File.expand_path('../lib/lazy_resource/version', __FILE__)
|
|
4
4
|
Gem::Specification.new do |gem|
|
5
5
|
gem.authors = ["Andrew Latimer"]
|
6
6
|
gem.email = ["andrew@elpasoera.com"]
|
7
|
-
gem.description = %q{ActiveResource with
|
8
|
-
gem.summary = %q{ActiveResource with
|
7
|
+
gem.description = %q{ActiveResource with its feet up. The write less, do more consumer of delicious APIs.}
|
8
|
+
gem.summary = %q{ActiveResource with its feet up. The write less, do more consumer of delicious APIs.}
|
9
9
|
gem.homepage = "http://github.com/ahlatimer/lazy_resource"
|
10
10
|
|
11
11
|
gem.files = `git ls-files`.split($\)
|
@@ -18,5 +18,5 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.add_dependency 'activemodel', '>= 3.1.0'
|
19
19
|
gem.add_dependency 'activesupport', '>= 3.1.0'
|
20
20
|
gem.add_dependency 'json', '>= 1.5.2'
|
21
|
-
gem.add_dependency 'typhoeus', '0.
|
21
|
+
gem.add_dependency 'typhoeus', '0.6.1'
|
22
22
|
end
|
@@ -73,8 +73,8 @@ module LazyResource
|
|
73
73
|
|
74
74
|
if @#{name}.nil?
|
75
75
|
@#{name} = LazyResource::Relation.new(#{type.first}, :fetched => true)
|
76
|
+
request = LazyResource::Request.new(self.#{options[:using]}, @#{name}, :headers => @#{name}.headers)
|
76
77
|
@#{name}.fetched = false
|
77
|
-
request = LazyResource::Request.new(self.#{options[:using]}, @#{name})
|
78
78
|
self.class.request_queue.queue(request)
|
79
79
|
end
|
80
80
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Typhoeus
|
2
2
|
class Hydra
|
3
3
|
def run_with_logging
|
4
|
-
log = LazyResource.debug && LazyResource.logger && @multi.
|
4
|
+
log = LazyResource.debug && LazyResource.logger && @multi.items_queued_but_not_running?
|
5
5
|
if log
|
6
6
|
LazyResource.logger.info "Processing requests:"
|
7
7
|
start_time = Time.now
|
@@ -17,8 +17,12 @@ module Typhoeus
|
|
17
17
|
alias_method :run_without_logging, :run
|
18
18
|
alias_method :run, :run_with_logging
|
19
19
|
end
|
20
|
+
end
|
20
21
|
|
22
|
+
module Ethon
|
21
23
|
class Multi
|
22
|
-
|
24
|
+
def items_queued_but_not_running?
|
25
|
+
easy_handles.size > 0 && running_count <= 0
|
26
|
+
end
|
23
27
|
end
|
24
28
|
end
|
@@ -4,14 +4,10 @@ module LazyResource
|
|
4
4
|
[:post, :put, :get, :delete].each do |method|
|
5
5
|
module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
6
6
|
def #{method}(path, body='', status=200, response_headers={})
|
7
|
-
|
7
|
+
Typhoeus.stub(path, :method => :#{method}).and_return(Typhoeus::Response.new(:code => status, :headers => response_headers, :body => body, :time => 0.3))
|
8
8
|
end
|
9
9
|
RUBY
|
10
10
|
end
|
11
|
-
|
12
|
-
def request_queue
|
13
|
-
Thread.current[:request_queue] ||= Typhoeus::Hydra.new
|
14
|
-
end
|
15
11
|
end
|
16
12
|
|
17
13
|
class << self
|
@@ -44,7 +44,7 @@ module LazyResource
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def mapped_root_node_name(objects)
|
47
|
-
if self.root_node_name
|
47
|
+
if self.root_node_name && objects.respond_to?(:keys)
|
48
48
|
root_node_names = self.root_node_name.is_a?(Array) ? self.root_node_name : [self.root_node_name]
|
49
49
|
mapped_name = (root_node_names.map(&:to_s) & objects.keys).first
|
50
50
|
end
|
@@ -53,6 +53,7 @@ module LazyResource
|
|
53
53
|
|
54
54
|
def load(hash, persisted=true)
|
55
55
|
hash.fetched = true and return hash if hash.kind_of?(LazyResource::Mapping)
|
56
|
+
return if hash.nil?
|
56
57
|
|
57
58
|
self.tap do |resource|
|
58
59
|
resource.persisted = persisted
|
@@ -42,10 +42,10 @@ module LazyResource
|
|
42
42
|
def load(objects)
|
43
43
|
@fetched = true
|
44
44
|
|
45
|
-
if @klass.
|
46
|
-
|
47
|
-
objects =
|
48
|
-
@other_attributes =
|
45
|
+
if mapped_name = @klass.mapped_root_node_name(objects)
|
46
|
+
other_attributes = objects.dup
|
47
|
+
objects = other_attributes.delete(mapped_name)
|
48
|
+
@other_attributes = other_attributes
|
49
49
|
end
|
50
50
|
|
51
51
|
@result = objects.map do |object|
|
@@ -14,18 +14,14 @@ module LazyResource
|
|
14
14
|
super(url, options)
|
15
15
|
|
16
16
|
@resource = resource
|
17
|
-
self.on_complete
|
18
|
-
|
19
|
-
self
|
20
|
-
end
|
21
|
-
|
22
|
-
def on_complete_proc
|
23
|
-
Proc.new do |response|
|
17
|
+
self.on_complete do
|
24
18
|
log_response(response) if LazyResource.debug && LazyResource.logger
|
25
19
|
@response = response
|
26
20
|
handle_errors unless SUCCESS_STATUSES.include?(@response.code)
|
27
21
|
parse
|
28
22
|
end
|
23
|
+
|
24
|
+
self
|
29
25
|
end
|
30
26
|
|
31
27
|
def log_response(response)
|
@@ -91,9 +91,9 @@ describe LazyResource::Attributes do
|
|
91
91
|
end
|
92
92
|
|
93
93
|
it 'finds a collection using the specified url' do
|
94
|
-
relation = LazyResource::Relation.new(Post)
|
94
|
+
relation = LazyResource::Relation.new(Post, :headers => {})
|
95
95
|
request = LazyResource::Request.new(@foo.posts_url, relation)
|
96
|
-
LazyResource::Request.should_receive(:new).with(@foo.posts_url, relation).and_return(request)
|
96
|
+
LazyResource::Request.should_receive(:new).with(@foo.posts_url, relation, :headers => relation.headers).and_return(request)
|
97
97
|
LazyResource::Relation.should_receive(:new).with(Post, :fetched => true).and_return(relation)
|
98
98
|
@foo.class.request_queue.should_receive(:queue).with(request)
|
99
99
|
@foo.fetched = false
|
@@ -17,22 +17,22 @@ describe Typhoeus::Hydra do
|
|
17
17
|
end
|
18
18
|
|
19
19
|
it 'logs if logging is enabled, there are items to process, and the queue has not yet started processing' do
|
20
|
-
@multi.
|
21
|
-
@multi.
|
20
|
+
@multi.stub!(:easy_handles).and_return([1,2,3])
|
21
|
+
@multi.stub!(:running_count).and_return(0)
|
22
22
|
LazyResource.logger.should_receive(:info).twice
|
23
23
|
@hydra.run_with_logging
|
24
24
|
end
|
25
25
|
|
26
26
|
it 'does not log if there are no items to process' do
|
27
|
-
@multi.
|
28
|
-
@multi.
|
27
|
+
@multi.stub!(:easy_handles).and_return([])
|
28
|
+
@multi.stub!(:running_count).and_return(0)
|
29
29
|
LazyResource.logger.should_not_receive(:info)
|
30
30
|
@hydra.run_with_logging
|
31
31
|
end
|
32
32
|
|
33
33
|
it 'does not log if the queue is already being processed' do
|
34
|
-
@multi.
|
35
|
-
@multi.
|
34
|
+
@multi.stub!(:easy_handles).and_return([1,2,3])
|
35
|
+
@multi.stub!(:running_count).and_return(3)
|
36
36
|
LazyResource.logger.should_not_receive(:info)
|
37
37
|
@hydra.run_with_logging
|
38
38
|
end
|
@@ -24,7 +24,8 @@ describe LazyResource do
|
|
24
24
|
it 'logs when a request completes' do
|
25
25
|
LazyResource.logger.should_receive(:info)
|
26
26
|
request = LazyResource::Request.new('http://example.com', User.new)
|
27
|
-
request.
|
27
|
+
request.response = Typhoeus::Response.new
|
28
|
+
request.execute_callbacks
|
28
29
|
end
|
29
30
|
end
|
30
31
|
end
|
@@ -75,6 +75,18 @@ describe LazyResource::Mapping do
|
|
75
75
|
user.comments.to_a.should == @comments
|
76
76
|
end
|
77
77
|
|
78
|
+
it 'should not attempt to load nil associations' do
|
79
|
+
user = Foo.load({
|
80
|
+
:id => 123,
|
81
|
+
:name => 'Andrew',
|
82
|
+
:post => nil
|
83
|
+
})
|
84
|
+
|
85
|
+
user.id.should == 123
|
86
|
+
user.name.should == 'Andrew'
|
87
|
+
user.post.should == nil
|
88
|
+
end
|
89
|
+
|
78
90
|
it 'loads an array of objects' do
|
79
91
|
users = Foo.load([
|
80
92
|
{
|
@@ -163,17 +175,44 @@ describe LazyResource::Mapping do
|
|
163
175
|
user.other_attributes.should == { 'length' => 12 }
|
164
176
|
end
|
165
177
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
178
|
+
describe 'multiple root node names' do
|
179
|
+
it 'supports multiple root node names with an instantiated object' do
|
180
|
+
Foo.root_node_name = [:data, :datum]
|
181
|
+
user = Foo.new
|
182
|
+
user.load('data' => { :id => 123 })
|
183
|
+
user.id.should == 123
|
184
|
+
end
|
185
|
+
|
186
|
+
it 'suppors multiple root node names with a single resource' do
|
187
|
+
Foo.root_node_name = [:data, :datum]
|
188
|
+
user = Foo.load('data' => { :id => 123 })
|
189
|
+
user.id.should == 123
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'supports multiple root node names with a collection' do
|
193
|
+
Foo.root_node_name = [:data, :datum]
|
194
|
+
users = Foo.load('data' => [{ :id => 123 }, { :id => 124 }])
|
195
|
+
users.map(&:id).should == [123, 124]
|
196
|
+
end
|
172
197
|
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
198
|
+
it 'sets any other attributes in the hash to #other_attributes for an instantiated object' do
|
199
|
+
Foo.root_node_name = [:data, :datum]
|
200
|
+
user = Foo.new
|
201
|
+
user.load('data' => { :id => 123 }, 'length' => 12)
|
202
|
+
user.other_attributes.should == { 'length' => 12 }
|
203
|
+
end
|
204
|
+
|
205
|
+
it 'sets any other attributes in the hash to #other_attributes for a single resource' do
|
206
|
+
Foo.root_node_name = [:data, :datum]
|
207
|
+
user = Foo.load('data' => { :id => 123 }, 'length' => 12)
|
208
|
+
user.other_attributes.should == { 'length' => 12 }
|
209
|
+
end
|
210
|
+
|
211
|
+
it 'sets any other attributes in the hash to #other_attributes for a collection' do
|
212
|
+
Foo.root_node_name = [:data, :datum]
|
213
|
+
users = Foo.load('data' => [{ :id => 123 }, { :id => 124 }], 'length' => 12)
|
214
|
+
users.other_attributes.should == { 'length' => 12 }
|
215
|
+
end
|
177
216
|
end
|
178
217
|
end
|
179
218
|
|
@@ -22,40 +22,18 @@ describe LazyResource::Request do
|
|
22
22
|
|
23
23
|
it 'sets a default Accept header of application/json' do
|
24
24
|
request = LazyResource::Request.new('http://example.com/api', nil)
|
25
|
-
|
26
|
-
headers[:Accept].should == 'application/json'
|
25
|
+
request.options[:headers][:Accept].should == 'application/json'
|
27
26
|
end
|
28
27
|
|
29
28
|
it 'sets the default method of GET' do
|
30
29
|
request = LazyResource::Request.new('http://example.com/api', nil)
|
31
|
-
request.
|
30
|
+
request.options[:method].should == :get
|
32
31
|
end
|
33
32
|
|
34
33
|
it 'merges the headers from the current thread' do
|
35
34
|
Thread.current[:default_headers] = { :"X-Access-Token" => 'abc' }
|
36
35
|
request = LazyResource::Request.new('http://example.com/api', nil)
|
37
|
-
|
38
|
-
headers[:"X-Access-Token"].should == 'abc'
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
describe '#on_complete_proc' do
|
43
|
-
it 'raises an error unless 200 or 201' do
|
44
|
-
request = LazyResource::Request.new('http://example.com', nil)
|
45
|
-
response = Typhoeus::Response.new(:code => 404, :headers => {}, :body => '', :time => 0.3)
|
46
|
-
lambda { request.on_complete_proc.call(response) }.should raise_error(LazyResource::ConnectionError)
|
47
|
-
end
|
48
|
-
|
49
|
-
it 'does not raise an error on 200' do
|
50
|
-
request = LazyResource::Request.new('http://example.com', SampleResource.new)
|
51
|
-
response = Typhoeus::Response.new(:code => 200)
|
52
|
-
lambda { request.on_complete_proc.call(response) }.should_not raise_error(StandardError)
|
53
|
-
end
|
54
|
-
|
55
|
-
it 'does not raise an error on 201' do
|
56
|
-
request = LazyResource::Request.new('http://example.com', SampleResource.new)
|
57
|
-
response = Typhoeus::Response.new(:code => 201)
|
58
|
-
lambda { request.on_complete_proc.call(response) }.should_not raise_error(StandardError)
|
36
|
+
request.options[:headers][:"X-Access-Token"].should == 'abc'
|
59
37
|
end
|
60
38
|
end
|
61
39
|
|
@@ -3,10 +3,6 @@ require 'spec_helper'
|
|
3
3
|
class Admin < User; end
|
4
4
|
|
5
5
|
describe LazyResource::Resource do
|
6
|
-
before :each do
|
7
|
-
Thread.current[:request_queue].clear_stubs unless Thread.current[:request_queue].nil?
|
8
|
-
end
|
9
|
-
|
10
6
|
describe '#new' do
|
11
7
|
it 'creates an object with the specified attributes' do
|
12
8
|
user = User.new({ :name => 'Andrew', :id => 123 })
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lazy_resource
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-02-15 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activemodel
|
@@ -66,7 +66,7 @@ dependencies:
|
|
66
66
|
requirements:
|
67
67
|
- - '='
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version: 0.
|
69
|
+
version: 0.6.1
|
70
70
|
type: :runtime
|
71
71
|
prerelease: false
|
72
72
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -74,8 +74,8 @@ dependencies:
|
|
74
74
|
requirements:
|
75
75
|
- - '='
|
76
76
|
- !ruby/object:Gem::Version
|
77
|
-
version: 0.
|
78
|
-
description: ActiveResource with
|
77
|
+
version: 0.6.1
|
78
|
+
description: ActiveResource with its feet up. The write less, do more consumer of
|
79
79
|
delicious APIs.
|
80
80
|
email:
|
81
81
|
- andrew@elpasoera.com
|
@@ -137,7 +137,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
137
137
|
version: '0'
|
138
138
|
segments:
|
139
139
|
- 0
|
140
|
-
hash: -
|
140
|
+
hash: -3444122050560505401
|
141
141
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
142
142
|
none: false
|
143
143
|
requirements:
|
@@ -146,13 +146,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
146
146
|
version: '0'
|
147
147
|
segments:
|
148
148
|
- 0
|
149
|
-
hash: -
|
149
|
+
hash: -3444122050560505401
|
150
150
|
requirements: []
|
151
151
|
rubyforge_project:
|
152
152
|
rubygems_version: 1.8.24
|
153
153
|
signing_key:
|
154
154
|
specification_version: 3
|
155
|
-
summary: ActiveResource with
|
155
|
+
summary: ActiveResource with its feet up. The write less, do more consumer of delicious
|
156
156
|
APIs.
|
157
157
|
test_files:
|
158
158
|
- spec/fixtures/comment.rb
|