lazy_resource 0.3.0 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -13,3 +13,4 @@ gem 'rspec'
13
13
  gem 'simplecov', :require => false
14
14
  gem 'guard-rspec'
15
15
  gem 'growl'
16
+ gem 'rb-fsevent'
data/Guardfile CHANGED
@@ -1,4 +1,4 @@
1
- guard 'rspec', :version => 2, :cli => "--color --format documentation" do
1
+ guard 'rspec', :cli => "--color --format documentation" do
2
2
  watch(%r{^spec/.+_spec\.rb$})
3
3
  watch(%r{^lib/lazy_resource/(.+)\.rb$}) { |m| "spec/lazy_resource/#{m[1]}_spec.rb" }
4
4
  watch('spec/spec_helper.rb') { "spec" }
@@ -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.2.4'
21
+ gem.add_dependency 'typhoeus', '0.4.2'
22
22
  end
data/lib/lazy_resource.rb CHANGED
@@ -21,9 +21,12 @@ require 'active_support/core_ext/uri'
21
21
  require 'lazy_resource/version'
22
22
  require 'lazy_resource/errors'
23
23
 
24
+ require 'lazy_resource/ext/typhoeus'
25
+
24
26
  module LazyResource
25
27
  extend ActiveSupport::Autoload
26
28
 
29
+ autoload :ConfigurationDelegate
27
30
  autoload :Attributes
28
31
  autoload :Mapping
29
32
  autoload :Relation
@@ -34,6 +37,22 @@ module LazyResource
34
37
  autoload :UrlGeneration
35
38
 
36
39
  def self.configure(&block)
37
- yield Resource
40
+ yield LazyResource::ConfigurationDelegate.new
41
+ end
42
+
43
+ def self.logger=(logger)
44
+ @logger = logger
45
+ end
46
+
47
+ def self.logger
48
+ @logger
49
+ end
50
+
51
+ def self.debug=(debug)
52
+ @debug = debug
53
+ end
54
+
55
+ def self.debug
56
+ @debug = @debug.nil? ? false : @debug
38
57
  end
39
58
  end
@@ -0,0 +1,14 @@
1
+ module LazyResource
2
+ class ConfigurationDelegate
3
+ def method_missing(method_name, *args, &block)
4
+ [LazyResource::Resource, LazyResource].each do |klass|
5
+ if klass.respond_to?(method_name)
6
+ return klass.send(method_name, *args, &block)
7
+ end
8
+ end
9
+
10
+ # if we didn't return from the each above, the method wasn't found
11
+ super
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,24 @@
1
+ module Typhoeus
2
+ class Hydra
3
+ def run_with_logging
4
+ log = LazyResource.debug && LazyResource.logger && @multi.active > 0 && @multi.running <= 0
5
+ if log
6
+ LazyResource.logger.info "Processing requests:"
7
+ start_time = Time.now
8
+ end
9
+
10
+ run_without_logging
11
+
12
+ if log
13
+ LazyResource.logger.info "Requests processed in #{((Time.now - start_time) * 1000).ceil}ms"
14
+ end
15
+ end
16
+
17
+ alias_method :run_without_logging, :run
18
+ alias_method :run, :run_with_logging
19
+ end
20
+
21
+ class Multi
22
+ attr_reader :active, :running
23
+ end
24
+ end
@@ -2,7 +2,7 @@ module LazyResource
2
2
  module Mapping
3
3
  extend ActiveSupport::Concern
4
4
 
5
- attr_accessor :fetched, :persisted
5
+ attr_accessor :fetched, :persisted, :other_attributes
6
6
 
7
7
  def fetched?
8
8
  @fetched
@@ -26,13 +26,17 @@ module LazyResource
26
26
  end
27
27
 
28
28
  def load(objects)
29
+ objects.fetched = true and return objects if objects.kind_of?(LazyResource::Mapping)
30
+
29
31
  if objects.is_a?(Array)
30
- objects.map do |object|
31
- self.new.load(object)
32
+ Relation.new(self, :fetched => true).tap do |relation|
33
+ relation.load(objects)
32
34
  end
33
35
  else
34
36
  if self.root_node_name && objects.key?(self.root_node_name.to_s)
35
- self.load(objects[self.root_node_name.to_s])
37
+ self.load(objects.delete(self.root_node_name.to_s)).tap do |obj|
38
+ obj.other_attributes = objects
39
+ end
36
40
  else
37
41
  self.new.load(objects)
38
42
  end
@@ -46,8 +50,13 @@ module LazyResource
46
50
  self.tap do |resource|
47
51
  resource.persisted = persisted
48
52
  resource.fetched = false
49
-
50
- hash = hash[resource.class.root_node_name.to_s] if resource.class.root_node_name && hash.key?(resource.class.root_node_name.to_s)
53
+
54
+ if resource.class.root_node_name && hash.key?(resource.class.root_node_name.to_s)
55
+ other_attributes = hash
56
+ hash = other_attributes.delete(resource.class.root_node_name.to_s)
57
+ self.other_attributes = other_attributes
58
+ end
59
+
51
60
  hash.each do |name, value|
52
61
  attribute = self.class.attributes[name.to_sym]
53
62
  next if attribute.nil?
@@ -8,7 +8,7 @@ module LazyResource
8
8
  end
9
9
  end
10
10
 
11
- attr_accessor :fetched, :klass, :values, :from, :site
11
+ attr_accessor :fetched, :klass, :values, :from, :site, :other_attributes
12
12
 
13
13
  def initialize(klass, options = {})
14
14
  @klass = klass
@@ -22,7 +22,7 @@ module LazyResource
22
22
  end
23
23
 
24
24
  def from
25
- @from || self.klass.collection_name
25
+ @from || self.klass.from || self.klass.collection_name
26
26
  end
27
27
 
28
28
  def collection_name
@@ -41,7 +41,20 @@ module LazyResource
41
41
 
42
42
  def load(objects)
43
43
  @fetched = true
44
- @result = @klass.load(objects)
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
49
+ end
50
+
51
+ @result = objects.map do |object|
52
+ @klass.load(object)
53
+ end
54
+ end
55
+
56
+ def headers
57
+ @headers ||= @klass.default_headers
45
58
  end
46
59
 
47
60
  def resource_queue
@@ -21,12 +21,17 @@ module LazyResource
21
21
 
22
22
  def on_complete_proc
23
23
  Proc.new do |response|
24
+ log_response(response) if LazyResource.debug && LazyResource.logger
24
25
  @response = response
25
26
  handle_errors unless SUCCESS_STATUSES.include?(@response.code)
26
27
  parse
27
28
  end
28
29
  end
29
30
 
31
+ def log_response(response)
32
+ LazyResource.logger.info "\t[#{response.code}](#{((response.time || 0) * 1000).ceil}ms): #{self.url}"
33
+ end
34
+
30
35
  def parse
31
36
  unless self.response.body.nil? || self.response.body == ''
32
37
  @resource.load(JSON.parse(self.response.body))
@@ -19,6 +19,14 @@ module LazyResource
19
19
  @site
20
20
  end
21
21
 
22
+ def self.default_headers=(headers)
23
+ @default_headers = headers
24
+ end
25
+
26
+ def self.default_headers
27
+ @default_headers || {}
28
+ end
29
+
22
30
  def self.root_node_name=(node_name)
23
31
  LazyResource::Mapping.root_node_name = node_name
24
32
  end
@@ -35,11 +43,23 @@ module LazyResource
35
43
  end
36
44
 
37
45
  # Sets the URI of the REST resources to map for this class to the value in the +site+ argument.
38
- # The site variable is required for Active Async's mapping to work.
46
+ # The site variable is required for LazyResources's mapping to work.
39
47
  def site=(site)
40
48
  @site = site
41
49
  end
42
50
 
51
+ def default_headers
52
+ if defined?(@default_headers)
53
+ @default_headers
54
+ else
55
+ LazyResource::Resource.default_headers
56
+ end
57
+ end
58
+
59
+ def default_headers=(headers)
60
+ @default_headers = headers
61
+ end
62
+
43
63
  def from
44
64
  @from
45
65
  end
@@ -56,6 +76,8 @@ module LazyResource
56
76
  self.new(self.primary_key_name => id).tap do |resource|
57
77
  resource.fetched = false
58
78
  resource.persisted = true
79
+ options[:headers] ||= {}
80
+ options[:headers].reverse_merge!(default_headers)
59
81
  request = Request.new(resource.element_url(params), resource, options)
60
82
  request_queue.queue(request)
61
83
  end
@@ -25,7 +25,7 @@ module LazyResource
25
25
 
26
26
  def send_to_request_queue!
27
27
  while(relation = @queue.pop)
28
- request = Request.new(url_for(relation), relation)
28
+ request = Request.new(url_for(relation), relation, :headers => relation.headers)
29
29
  request_queue.queue(request)
30
30
  end
31
31
  end
@@ -1,3 +1,3 @@
1
1
  module LazyResource
2
- VERSION = "0.3.0"
2
+ VERSION = "0.3.2"
3
3
  end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ describe LazyResource::ConfigurationDelegate do
4
+ subject { LazyResource::ConfigurationDelegate.new }
5
+ it 'forwards the method invocation to Resource if the method is defined there' do
6
+ subject.site.should == 'http://example.com'
7
+ end
8
+
9
+ it 'forwards the invocation to LazyResource if the method is defined there' do
10
+ subject.debug.should == false
11
+ end
12
+
13
+ it 'raises an error if the method is not defined on one of the delegated classes' do
14
+ lambda { subject.foo }.should raise_error(NoMethodError)
15
+ end
16
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ class SimpleLogger
4
+ def info(msg)
5
+ msg
6
+ end
7
+ end
8
+
9
+ describe Typhoeus::Hydra do
10
+ describe '#run_with_logging' do
11
+ before :each do
12
+ LazyResource.debug = true
13
+ LazyResource.logger = SimpleLogger.new
14
+ @hydra = Typhoeus::Hydra.new
15
+ @hydra.stub!(:run_without_logging)
16
+ @multi = @hydra.send(:instance_variable_get, :"@multi")
17
+ end
18
+
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)
22
+ LazyResource.logger.should_receive(:info).twice
23
+ @hydra.run_with_logging
24
+ end
25
+
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)
29
+ LazyResource.logger.should_not_receive(:info)
30
+ @hydra.run_with_logging
31
+ end
32
+
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)
36
+ LazyResource.logger.should_not_receive(:info)
37
+ @hydra.run_with_logging
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ class DumbLogger
4
+ def info(msg)
5
+ puts msg
6
+ end
7
+ end
8
+
9
+ describe LazyResource do
10
+ before :each do
11
+ LazyResource.configure do |config|
12
+ config.debug = true
13
+ config.logger = DumbLogger.new
14
+ end
15
+ end
16
+
17
+ describe '#logger' do
18
+ it 'returns the logger' do
19
+ LazyResource.logger.should_not be_nil
20
+ end
21
+ end
22
+
23
+ describe '#debug' do
24
+ it 'logs when a request completes' do
25
+ LazyResource.logger.should_receive(:info)
26
+ request = LazyResource::Request.new('http://example.com', User.new)
27
+ request.on_complete_proc.call(Typhoeus::Response.new)
28
+ end
29
+ end
30
+ end
@@ -72,7 +72,7 @@ describe LazyResource::Mapping do
72
72
  user.name.should == 'Andrew'
73
73
  user.created_at.should == @now
74
74
  user.post.should == @post
75
- user.comments.should == @comments
75
+ user.comments.to_a.should == @comments
76
76
  end
77
77
 
78
78
  it 'loads an array of objects' do
@@ -143,6 +143,25 @@ describe LazyResource::Mapping do
143
143
  user = Foo.load('data' => { :id => 123 })
144
144
  user.id.should == 123
145
145
  end
146
+
147
+ it 'sets any other attributes in the hash to #other_attributes for a single resource' do
148
+ Foo.root_node_name = :data
149
+ user = Foo.load('data' => { :id => 123 }, 'length' => 12)
150
+ user.other_attributes.should == { 'length' => 12 }
151
+ end
152
+
153
+ it 'sets any other attributes in the hash to #other_attributes for a collection' do
154
+ Foo.root_node_name = :data
155
+ users = Foo.load('data' => [{:id => 123}], 'length' => 12)
156
+ users.other_attributes.should == { 'length' => 12 }
157
+ end
158
+
159
+ it 'sets any other attributes in the hash to #other_attributes for an instantiated object' do
160
+ Foo.root_node_name = :data
161
+ user = Foo.new
162
+ user.load('data' => { :id => 123 }, 'length' => 12)
163
+ user.other_attributes.should == { 'length' => 12 }
164
+ end
146
165
  end
147
166
 
148
167
  describe '#load' do
@@ -25,7 +25,15 @@ describe LazyResource::Relation do
25
25
  users = [{ :id => '1', :name => 'Andrew' }, { :id => '1', :name => 'James' }]
26
26
  users_collection = LazyResource::Relation.new(User)
27
27
  users_collection.load(users)
28
- users_collection.to_a.should == User.load(users)
28
+ users_collection.to_a.should == User.load(users).to_a
29
+ end
30
+
31
+ it 'adds any other attributes to #other_attributes' do
32
+ User.root_node_name = :data
33
+ users = { 'data' => [{ :id => '1', :name => 'Andrew' }, { :id => '1', :name => 'James' }], 'length' => 12 }
34
+ users_collection = LazyResource::Relation.new(User)
35
+ users_collection.load(users)
36
+ users_collection.other_attributes.should == { 'length' => 12 }
29
37
  end
30
38
  end
31
39
 
@@ -259,6 +259,10 @@ describe LazyResource::Resource do
259
259
  end
260
260
  end
261
261
 
262
+ after :each do
263
+ User.default_headers = {}
264
+ end
265
+
262
266
  it 'generates a new resource and associated request and adds it to the request queue' do
263
267
  LazyResource::Request.should_receive(:new)
264
268
  User.request_queue.should_receive(:queue)
@@ -276,6 +280,20 @@ describe LazyResource::Resource do
276
280
  user = User.find(1)
277
281
  user.name.should == 'Andrew'
278
282
  end
283
+
284
+ it 'uses default headers' do
285
+ User.default_headers = { :foo => 'bar' }
286
+ request = LazyResource::Request.new('/path/to/something', User.new)
287
+ LazyResource::Request.should_receive(:new).with(anything, anything, :headers => { :foo => 'bar' }).and_return(request)
288
+ User.find(1)
289
+ end
290
+
291
+ it 'allows default headers to be overwritten' do
292
+ User.default_headers = { :foo => 'bar' }
293
+ request = LazyResource::Request.new('/path/to/something', User.new)
294
+ LazyResource::Request.should_receive(:new).with(anything, anything, :headers => { :foo => 'buzz' }).and_return(request)
295
+ User.find(1, {}, { :headers => { :foo => 'buzz' } })
296
+ end
279
297
  end
280
298
 
281
299
  describe '.where' do
@@ -379,6 +397,55 @@ describe LazyResource::Resource do
379
397
  end
380
398
  end
381
399
 
400
+ describe '.default_headers' do
401
+ after :each do
402
+ User.default_headers = {}
403
+ end
404
+
405
+ it 'returns the default headers if they are defined' do
406
+ User.default_headers = { :foo => 'bar' }
407
+ User.default_headers.should == { :foo => 'bar' }
408
+ end
409
+
410
+ it 'returns LazyResource::Resource.default_headers if default_headers is not defined' do
411
+ User.send(:remove_instance_variable, "@default_headers")
412
+ User.default_headers.should == LazyResource::Resource.default_headers
413
+ end
414
+ end
415
+
416
+ describe '.default_headers=' do
417
+ after :each do
418
+ User.default_headers = {}
419
+ end
420
+
421
+ it 'sets the default headers' do
422
+ User.default_headers = { :foo => 'bar' }
423
+ User.default_headers.should == { :foo => 'bar' }
424
+ end
425
+ end
426
+
427
+ describe 'self.default_headers' do
428
+ after :each do
429
+ LazyResource::Resource.default_headers = {}
430
+ end
431
+
432
+ it 'returns the global default headers' do
433
+ LazyResource::Resource.default_headers = { :foo => 'bar' }
434
+ LazyResource::Resource.default_headers.should == { :foo => 'bar' }
435
+ end
436
+ end
437
+
438
+ describe 'self.default_headers=' do
439
+ after :each do
440
+ LazyResource::Resource.default_headers = {}
441
+ end
442
+
443
+ it 'sets the global default headers' do
444
+ LazyResource::Resource.default_headers = { :foo => 'bar' }
445
+ LazyResource::Resource.default_headers.should == { :foo => 'bar' }
446
+ end
447
+ end
448
+
382
449
  describe '.from' do
383
450
  before :each do
384
451
  @from = User.from
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.0
4
+ version: 0.3.2
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-08-20 00:00:00.000000000 Z
12
+ date: 2012-12-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activemodel
@@ -64,17 +64,17 @@ dependencies:
64
64
  requirement: !ruby/object:Gem::Requirement
65
65
  none: false
66
66
  requirements:
67
- - - ! '>='
67
+ - - '='
68
68
  - !ruby/object:Gem::Version
69
- version: 0.2.4
69
+ version: 0.4.2
70
70
  type: :runtime
71
71
  prerelease: false
72
72
  version_requirements: !ruby/object:Gem::Requirement
73
73
  none: false
74
74
  requirements:
75
- - - ! '>='
75
+ - - '='
76
76
  - !ruby/object:Gem::Version
77
- version: 0.2.4
77
+ version: 0.4.2
78
78
  description: ActiveResource with it's feet up. The write less, do more consumer of
79
79
  delicious APIs.
80
80
  email:
@@ -95,7 +95,9 @@ files:
95
95
  - lazy_resource.gemspec
96
96
  - lib/lazy_resource.rb
97
97
  - lib/lazy_resource/attributes.rb
98
+ - lib/lazy_resource/configuration_delegate.rb
98
99
  - lib/lazy_resource/errors.rb
100
+ - lib/lazy_resource/ext/typhoeus.rb
99
101
  - lib/lazy_resource/http_mock.rb
100
102
  - lib/lazy_resource/mapping.rb
101
103
  - lib/lazy_resource/relation.rb
@@ -109,7 +111,10 @@ files:
109
111
  - spec/fixtures/post.rb
110
112
  - spec/fixtures/user.rb
111
113
  - spec/lazy_resource/attributes_spec.rb
114
+ - spec/lazy_resource/configuration_delegate_spec.rb
112
115
  - spec/lazy_resource/errors_spec.rb
116
+ - spec/lazy_resource/ext/typhoeus_spec.rb
117
+ - spec/lazy_resource/lazy_resource_spec.rb
113
118
  - spec/lazy_resource/mapping_spec.rb
114
119
  - spec/lazy_resource/relation_spec.rb
115
120
  - spec/lazy_resource/request_spec.rb
@@ -132,7 +137,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
132
137
  version: '0'
133
138
  segments:
134
139
  - 0
135
- hash: -2886530034829089377
140
+ hash: 1900980543301721831
136
141
  required_rubygems_version: !ruby/object:Gem::Requirement
137
142
  none: false
138
143
  requirements:
@@ -141,7 +146,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
141
146
  version: '0'
142
147
  segments:
143
148
  - 0
144
- hash: -2886530034829089377
149
+ hash: 1900980543301721831
145
150
  requirements: []
146
151
  rubyforge_project:
147
152
  rubygems_version: 1.8.24
@@ -154,7 +159,10 @@ test_files:
154
159
  - spec/fixtures/post.rb
155
160
  - spec/fixtures/user.rb
156
161
  - spec/lazy_resource/attributes_spec.rb
162
+ - spec/lazy_resource/configuration_delegate_spec.rb
157
163
  - spec/lazy_resource/errors_spec.rb
164
+ - spec/lazy_resource/ext/typhoeus_spec.rb
165
+ - spec/lazy_resource/lazy_resource_spec.rb
158
166
  - spec/lazy_resource/mapping_spec.rb
159
167
  - spec/lazy_resource/relation_spec.rb
160
168
  - spec/lazy_resource/request_spec.rb