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 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
 
@@ -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 it's feet up. The write less, do more consumer of delicious APIs.}
8
- gem.summary = %q{ActiveResource with it's feet up. The write less, do more consumer of delicious APIs.}
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.4.2'
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.active > 0 && @multi.running <= 0
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
- attr_reader :active, :running
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
- request_queue.stub(:#{method}, path).and_return(Typhoeus::Response.new(:code => status, :headers => response_headers, :body => body, :time => 0.3))
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.root_node_name && objects.respond_to?(:key?) && objects.key?(@klass.root_node_name.to_s)
46
- other_objects = objects.dup
47
- objects = other_objects.delete(@klass.root_node_name.to_s)
48
- @other_attributes = other_objects
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 = on_complete_proc
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)
@@ -1,3 +1,3 @@
1
1
  module LazyResource
2
- VERSION = "0.3.3"
2
+ VERSION = "0.4.0"
3
3
  end
@@ -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.send(:instance_variable_set, "@active", 10)
21
- @multi.send(:instance_variable_set, "@running", 0)
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.send(:instance_variable_set, "@active", 0)
28
- @multi.send(:instance_variable_set, "@running", 0)
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.send(:instance_variable_set, "@active", 10)
35
- @multi.send(:instance_variable_set, "@running", 5)
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.on_complete_proc.call(Typhoeus::Response.new)
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
- it 'supports multiple root node names with a single resource' do
167
- Foo.root_node_name = [:data, :datum]
168
- user = Foo.new
169
- user.load('data' => { :id => 123 })
170
- user.id.should == 123
171
- end
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
- it 'supports multiple root node names with a collection' do
174
- Foo.root_node_name = [:data, :datum]
175
- users = Foo.load('data' => [{ :id => 123 }, { :id => 124 }])
176
- users.map(&:id).should == [123, 124]
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
- headers = request.send(:instance_variable_get, "@headers")
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.send(:instance_variable_get, "@method").should == :get
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
- headers = request.send(:instance_variable_get, "@headers")
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.3.3
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: 2012-12-10 00:00:00.000000000 Z
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.4.2
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.4.2
78
- description: ActiveResource with it's feet up. The write less, do more consumer of
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: -809900452515726390
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: -809900452515726390
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 it's feet up. The write less, do more consumer of delicious
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