lazy_resource 0.3.0 → 0.3.2

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