carbon 0.2.5 → 0.2.6

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.5
1
+ 0.2.6
data/carbon.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{carbon}
8
- s.version = "0.2.5"
8
+ s.version = "0.2.6"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Derek Kastner", "Seamus Abshere", "Andy Rossmeissl"]
12
- s.date = %q{2010-08-02}
12
+ s.date = %q{2010-08-18}
13
13
  s.description = %q{Carbon is a Ruby API wrapper for the Brighter Planet emission estimate web service (http://carbon.brighterplanet.com). By querying the web service, it can estimate the carbon emissions of many real-life objects, such as cars and houses, based on particular attributes that they may have.}
14
14
  s.email = %q{derek.kastner@brighterplanet.com}
15
15
  s.extra_rdoc_files = [
@@ -33,6 +33,7 @@ Gem::Specification.new do |s|
33
33
  "lib/carbon/emission_estimate/request.rb",
34
34
  "lib/carbon/emission_estimate/response.rb",
35
35
  "lib/carbon/emission_estimate/storage.rb",
36
+ "spec/lib/carbon/emission_estimate/response_spec.rb",
36
37
  "spec/lib/carbon_spec.rb",
37
38
  "spec/spec_helper.rb",
38
39
  "spec/specwatchr"
@@ -43,7 +44,8 @@ Gem::Specification.new do |s|
43
44
  s.rubygems_version = %q{1.3.7}
44
45
  s.summary = %q{Carbon is a Ruby API wrapper for the Brighter Planet emission estimate web service (http://carbon.brighterplanet.com).}
45
46
  s.test_files = [
46
- "spec/lib/carbon_spec.rb",
47
+ "spec/lib/carbon/emission_estimate/response_spec.rb",
48
+ "spec/lib/carbon_spec.rb",
47
49
  "spec/spec_helper.rb"
48
50
  ]
49
51
 
data/lib/carbon.rb CHANGED
@@ -5,6 +5,7 @@ require 'digest/sha1'
5
5
  require 'rest' # provided by nap gem
6
6
  gem 'SystemTimer' # >=1.2, so as not to be confused with system_timer 1.0
7
7
  require 'system_timer'
8
+ require 'active_support'
8
9
  require 'active_support/version'
9
10
  %w{
10
11
  active_support/core_ext/module/attribute_accessors
data/lib/carbon/base.rb CHANGED
@@ -10,6 +10,7 @@ module Carbon
10
10
  @klass = klass
11
11
  @emitter_common_name = emitter_common_name.to_s
12
12
  end
13
+
13
14
  # A completed translation table will look like:
14
15
  # {[:mixer, :size]=>"mixer_size",
15
16
  # :personnel=>:employees,
@@ -19,6 +20,7 @@ module Carbon
19
20
  def translation_table # :nodoc:
20
21
  @translation_table ||= Hash.new
21
22
  end
23
+
22
24
  # Indicate that you will send in a piece of data about the emitter.
23
25
  #
24
26
  # Two general rules:
@@ -50,6 +52,7 @@ module Carbon
50
52
  # translation_table[:make] = 'epa_code'
51
53
  translation_table[characteristic] = options[:key]
52
54
  end
55
+
53
56
  # Third-person singular preferred.
54
57
  alias :provides :provide
55
58
  end
@@ -17,6 +17,15 @@ module Carbon
17
17
  data['updated_at'] = ::Time.parse(data['updated_at']) if data.has_key? 'updated_at'
18
18
  data
19
19
  end
20
+
21
+ attr_writer :callback_content_type
22
+ attr_writer :key
23
+ attr_writer :timeout
24
+ attr_writer :defer
25
+ attr_accessor :callback
26
+ attr_accessor :timeframe
27
+ attr_accessor :guid
28
+ attr_reader :emitter
20
29
 
21
30
  def initialize(emitter)
22
31
  @emitter = emitter
@@ -55,14 +64,7 @@ module Carbon
55
64
  super
56
65
  end
57
66
  end
58
- attr_writer :callback_content_type
59
- attr_writer :key
60
- attr_writer :timeout
61
- attr_writer :defer
62
- attr_accessor :callback
63
- attr_accessor :timeframe
64
- attr_accessor :guid
65
- attr_reader :emitter
67
+
66
68
  def data
67
69
  if storage.present?
68
70
  storage.data
@@ -70,58 +72,74 @@ module Carbon
70
72
  response.data
71
73
  end
72
74
  end
75
+
73
76
  def storage
74
77
  @storage ||= {}
75
78
  return @storage[guid] if @storage.has_key? guid
76
79
  @storage[guid] = Storage.new self
77
80
  end
81
+
78
82
  def request
79
83
  @request ||= Request.new self
80
84
  end
85
+
81
86
  # Here's where caching takes place.
82
87
  def response
83
88
  current_params = request.params
84
89
  @response ||= {}
85
90
  return @response[current_params] if @response.has_key? current_params
86
- @response[current_params] = Response.new self
91
+ response_object = Response.new self
92
+ response_object.load_data
93
+ @response[current_params] = response_object
87
94
  end
95
+
88
96
  def defer?
89
97
  @defer == true
90
98
  end
99
+
91
100
  def async?
92
101
  callback or defer?
93
102
  end
103
+
94
104
  def mode
95
105
  async? ? :async : :realtime
96
106
  end
107
+
97
108
  # Timeout on realtime requests in seconds, if desired.
98
109
  def timeout
99
110
  @timeout
100
111
  end
112
+
101
113
  def callback_content_type
102
114
  @callback_content_type || 'application/json'
103
115
  end
116
+
104
117
  def key
105
118
  @key || ::Carbon.key
106
119
  end
120
+
107
121
  # The timeframe being looked at in the emission calculation.
108
122
  def active_subtimeframe
109
123
  data['active_subtimeframe']
110
124
  end
125
+
111
126
  # Another way to access the emission value.
112
127
  # Useful if you don't like treating <tt>EmissionEstimate</tt> objects like <tt>Numeric</tt> objects (even though they do quack like numbers...)
113
128
  def number
114
129
  async? ? nil : data['emission'].to_f.freeze
115
130
  end
131
+
116
132
  # The units of the emission.
117
133
  def emission_units
118
134
  data['emission_units']
119
135
  end
136
+
120
137
  # Errors (and warnings) as reported in the response.
121
138
  # Note: may contain HTML tags like KBD or A
122
139
  def errors
123
140
  data['errors']
124
141
  end
142
+
125
143
  # The URL of the methodology report indicating how this estimate was calculated.
126
144
  # > my_car.emission_estimate.methodology
127
145
  # => 'http://carbon.brighterplanet.com/automobiles.html?[...]'
@@ -2,15 +2,19 @@ module Carbon
2
2
  class EmissionEstimate
3
3
  class Request
4
4
  attr_reader :parent
5
+
5
6
  def initialize(parent)
6
7
  @parent = parent
7
8
  end
9
+
8
10
  def body
9
11
  params.to_query
10
12
  end
13
+
11
14
  def params
12
15
  send "#{parent.mode}_params"
13
16
  end
17
+
14
18
  def async_params # :nodoc:
15
19
  raise ::ArgumentError, "When using :callback you cannot specify :defer" if parent.defer? and parent.callback
16
20
  raise ::ArgumentError, "When using :defer => true you must specify :guid" if parent.defer? and parent.guid.blank?
@@ -25,9 +29,11 @@ module Carbon
25
29
  :MessageBody => hash.to_query
26
30
  }
27
31
  end
32
+
28
33
  def realtime_params # :nodoc:
29
34
  _params
30
35
  end
36
+
31
37
  # Used internally, but you can look if you want.
32
38
  #
33
39
  # Returns the params hash that will be send to the emission estimate server.
@@ -60,12 +66,15 @@ module Carbon
60
66
  hash[:key] = parent.key if parent.key
61
67
  hash
62
68
  end
69
+
63
70
  def realtime_url # :nodoc:
64
71
  "#{::Carbon::REALTIME_URL}/#{parent.emitter.class.carbon_base.emitter_common_name.pluralize}.json"
65
72
  end
73
+
66
74
  def async_url # :nodoc:
67
75
  ::Carbon::ASYNC_URL
68
76
  end
77
+
69
78
  def url
70
79
  send "#{parent.mode}_url"
71
80
  end
@@ -5,17 +5,23 @@ module Carbon
5
5
  attr_reader :data
6
6
  attr_reader :raw_request
7
7
  attr_reader :raw_response
8
+
8
9
  def initialize(parent)
9
10
  @parent = parent
11
+ end
12
+
13
+ def load_data
10
14
  send "load_#{parent.mode}_data"
11
15
  end
16
+
17
+ private
12
18
  def load_realtime_data # :nodoc:
13
19
  attempts = 0
14
20
  response = nil
15
21
  begin
16
22
  response = perform
17
- raise ::Carbon::RateLimited if response.status_code == 403 and response.body =~ /Rate Limit/i
18
- rescue ::Carbon::RateLimited
23
+ raise ::Carbon::RateLimited if response.status_code == 403 and response.body =~ /Rate Limit/i #TODO: Should we expect an HTTP 402: payment required, instead?
24
+ rescue ::Carbon::RateLimited, EOFError
19
25
  if attempts < 4
20
26
  attempts += 1
21
27
  sleep 0.2 * attempts
@@ -24,26 +30,29 @@ module Carbon
24
30
  raise $!
25
31
  end
26
32
  end
27
- raise ::Carbon::RealtimeEstimateFailed unless response.success?
33
+ raise ::Carbon::RealtimeEstimateFailed unless response.success? #TODO: should we expect 300s as well as 200s? Also, we may want to include response code and body in our exception.
28
34
  @data = ::Carbon::EmissionEstimate.parse response.body
29
35
  end
36
+
30
37
  def load_async_data # :nodoc:
31
38
  response = perform
32
- raise ::Carbon::QueueingFailed unless response.success?
39
+ raise ::Carbon::QueueingFailed unless response.success? #TODO: should we expect 300s as well as 200s? Also, we may want to include response code and body in our exception.
33
40
  @data = {}
34
41
  end
42
+
35
43
  def perform # :nodoc:
36
44
  response = nil
37
45
  if parent.timeout
38
46
  ::SystemTimer.timeout_after(parent.timeout) do
39
- response = _perform
47
+ response = perform_request
40
48
  end
41
49
  else
42
- response = _perform
50
+ response = perform_request
43
51
  end
44
52
  response
45
53
  end
46
- def _perform # :nodoc:
54
+
55
+ def perform_request # :nodoc:
47
56
  @raw_request = ::REST::Request.new :post, ::URI.parse(parent.request.url), parent.request.body, {'Content-Type' => 'application/x-www-form-urlencoded; charset=utf-8'}
48
57
  @raw_response = raw_request.perform
49
58
  end
@@ -4,15 +4,19 @@ module Carbon
4
4
  attr_accessor :parent
5
5
  attr_reader :raw_request
6
6
  attr_reader :raw_response
7
+
7
8
  def initialize(parent)
8
9
  @parent = parent
9
10
  end
11
+
10
12
  def url
11
13
  "#{::Carbon::STORAGE_URL}/#{::Digest::SHA1.hexdigest(parent.key+parent.guid)}"
12
14
  end
15
+
13
16
  def present?
14
17
  parent.guid.present? and data.present?
15
18
  end
19
+
16
20
  def data
17
21
  return @data[0] if @data.is_a? ::Array
18
22
  @raw_request = ::REST::Request.new :get, ::URI.parse(url)
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe Carbon::EmissionEstimate::Response do
4
+ let(:parent) { mock(Object, :mode => :realtime) }
5
+ let(:response) { Carbon::EmissionEstimate::Response.new parent }
6
+ let(:rest_response) { mock(Object, :success? => true, :status_code => 200,
7
+ :body => 'OK') }
8
+
9
+ describe '#load_realtime_data' do
10
+ before do
11
+ ::Carbon::EmissionEstimate.stub! :parse
12
+ response.stub! :sleep
13
+ end
14
+
15
+ it 'should retry a request that is rate limited' do
16
+ response.should_receive(:perform).once.ordered.
17
+ and_raise ::Carbon::RateLimited
18
+ response.should_receive(:perform).once.ordered.
19
+ and_return rest_response
20
+
21
+ response.send :load_realtime_data
22
+ end
23
+
24
+ it 'should retry a request that gets cut off (server disappears mid-request)' do
25
+ response.should_receive(:perform).once.ordered.
26
+ and_raise EOFError
27
+ response.should_receive(:perform).once.ordered.
28
+ and_return rest_response
29
+
30
+ response.send :load_realtime_data
31
+ end
32
+ end
33
+ end
34
+
@@ -130,11 +130,11 @@ module Carbon
130
130
  attr_accessor :sleep_before_performing
131
131
  VALID_OPTIONS.push :sleep_before_performing
132
132
  class Response
133
- def _perform_with_delay
133
+ def perform_request_with_delay
134
134
  sleep parent.sleep_before_performing if parent.sleep_before_performing
135
- _perform_without_delay
135
+ perform_request_without_delay
136
136
  end
137
- alias_method_chain :_perform, :delay
137
+ alias_method_chain :perform_request, :delay
138
138
  end
139
139
  end
140
140
  end
data/spec/spec_helper.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  require 'rubygems'
2
2
  require 'rspec'
3
- begin
4
- require 'ruby-debug'
5
- rescue
6
- end
3
+ #begin
4
+ # require 'ruby-debug'
5
+ #rescue
6
+ #end
7
7
 
8
8
  require 'carbon'
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: carbon
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
4
+ hash: 27
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 2
9
- - 5
10
- version: 0.2.5
9
+ - 6
10
+ version: 0.2.6
11
11
  platform: ruby
12
12
  authors:
13
13
  - Derek Kastner
@@ -17,7 +17,7 @@ autorequire:
17
17
  bindir: bin
18
18
  cert_chain: []
19
19
 
20
- date: 2010-08-02 00:00:00 -04:00
20
+ date: 2010-08-18 00:00:00 -04:00
21
21
  default_executable:
22
22
  dependencies:
23
23
  - !ruby/object:Gem::Dependency
@@ -158,6 +158,7 @@ files:
158
158
  - lib/carbon/emission_estimate/request.rb
159
159
  - lib/carbon/emission_estimate/response.rb
160
160
  - lib/carbon/emission_estimate/storage.rb
161
+ - spec/lib/carbon/emission_estimate/response_spec.rb
161
162
  - spec/lib/carbon_spec.rb
162
163
  - spec/spec_helper.rb
163
164
  - spec/specwatchr
@@ -196,5 +197,6 @@ signing_key:
196
197
  specification_version: 3
197
198
  summary: Carbon is a Ruby API wrapper for the Brighter Planet emission estimate web service (http://carbon.brighterplanet.com).
198
199
  test_files:
200
+ - spec/lib/carbon/emission_estimate/response_spec.rb
199
201
  - spec/lib/carbon_spec.rb
200
202
  - spec/spec_helper.rb