lazy_resource 0.3.3 → 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/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
|