carbon 1.0.4 → 1.1.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/.gitignore CHANGED
@@ -20,3 +20,4 @@ pkg
20
20
 
21
21
  ## PROJECT::SPECIFIC
22
22
  Gemfile.lock
23
+ *.gem
data/README.rdoc CHANGED
@@ -154,7 +154,7 @@ It's telling you that a flight in 2009 did not result in any 2011 emissions (the
154
154
 
155
155
  So, 850 kilograms emitted in 2009.
156
156
 
157
- == Attribute serialization
157
+ == Association serialization
158
158
 
159
159
  Your objects' attributes are serialized via <tt>#to_characteristic</tt> or <tt>#to_param</tt> (in that order of preference) before being submitted to the web service.
160
160
 
@@ -180,6 +180,12 @@ Without <tt>AutomobileMake#to_characteristic</tt>, the library would have no way
180
180
 
181
181
  Runs a realtime request but allows timing out the network call. Raises <tt>Timeout::Error</tt> if timeout is exceeded.
182
182
 
183
+ == Certified calculations
184
+
185
+ You can run {certified calculations}[http://brighterplanet.com/certified] by setting <tt>certified</tt> to true.
186
+
187
+ > RentalCar.new.emission_estimate :certified => true
188
+
183
189
  == Persisted queries
184
190
 
185
191
  You can specify that the result be persisted in low-latency storage so that future identical requests can use the same estimate:
@@ -241,8 +247,12 @@ This library includes a special console for performing calculations interactivel
241
247
 
242
248
  === Emitter mode
243
249
 
250
+ In Emitter mode, the prompt displays the emitter type in use. If a timeframe has been set, the timeframe is also included in the prompt.
251
+
244
252
  [+help+] Displays a list of characteristics for this emitter type.
245
253
  [<tt><i>characteristic value</i></tt>] (e.g. <tt>origin_airport 'lax'</tt>) Provide a characteristic. Remember, this is Ruby we're dealing with, so strings must be quoted.
254
+ [+timeframe+] Display the current timeframe in effect on the emission estimate.
255
+ [<tt>timeframe <i>timeframe</i></tt>] (e.g. <tt>timeframe '2009-01-01/2010-01-01'</tt> or just <tt>timeframe '2009'</tt>) Set a timeframe on the emission estimate.
246
256
  [+emission+] Displays the current emission in kilograms CO2e for this emitter.
247
257
  [+lbs+, +pounds+, or +tons+] Display the emission using different units.
248
258
  [+characteristics+] Lists the characteristics you have provided so far.
data/Rakefile CHANGED
@@ -8,7 +8,8 @@ RSpec::Core::RakeTask.new('examples') do |c|
8
8
  c.rspec_opts = '-Ispec'
9
9
  end
10
10
 
11
- task :default => :examples
11
+ task :test => [:examples, :cucumber]
12
+ task :default => :test
12
13
 
13
14
  desc "Run specs with RCov"
14
15
  RSpec::Core::RakeTask.new(:examples_with_coverage) do |t|
@@ -26,3 +27,7 @@ Rake::RDocTask.new do |rdoc|
26
27
  rdoc.rdoc_files.include('README*')
27
28
  rdoc.rdoc_files.include('lib/**/*.rb')
28
29
  end
30
+
31
+ require 'cucumber/rake/task'
32
+ Cucumber::Rake::Task.new
33
+
data/bin/carbon CHANGED
@@ -3,15 +3,5 @@ $:.unshift(File.dirname(__FILE__) + '/../lib') unless $:.include?(File.dirname(_
3
3
 
4
4
  require 'rubygems'
5
5
  require 'carbon'
6
- require 'carbon/cli'
7
- begin
8
- # The dup is to keep ARGV intact, so that tools like ruby-debug can respawn.
9
- failure = Carbon::Cli.execute(ARGV.dup)
10
- Kernel.exit(failure ? 1 : 0)
11
- rescue SystemExit => e
12
- Kernel.exit(e.status)
13
- rescue Exception => e
14
- STDERR.puts("#{e.message} (#{e.class})")
15
- STDERR.puts(e.backtrace.join("\n"))
16
- Kernel.exit(1)
17
- end
6
+ require 'carbon/shell'
7
+ Bombshell.launch(Carbon::Shell)
data/carbon.gemspec CHANGED
@@ -25,6 +25,9 @@ Gem::Specification.new do |s|
25
25
  s.add_dependency 'timeframe'
26
26
  s.add_dependency 'blockenspiel'
27
27
  s.add_dependency 'conversions'
28
+ s.add_dependency 'brighter_planet_metadata'
29
+ s.add_dependency 'bombshell'
28
30
  s.add_development_dependency 'fakeweb'
29
31
  s.add_development_dependency 'rspec'
32
+ s.add_development_dependency 'aruba'
30
33
  end
@@ -0,0 +1,186 @@
1
+ Feature: Shell
2
+
3
+ In order to explore the CM1 API
4
+ As a potential client
5
+ I want to make simple calculations from an interactive console
6
+
7
+ Scenario: Running the shell
8
+ When I run `carbon` interactively
9
+ And I type "exit"
10
+ Then the output should contain:
11
+ """
12
+ carbon->
13
+ """
14
+
15
+ Scenario: Setting a key
16
+ When I run `carbon` interactively
17
+ And I type "key 'abc'"
18
+ And I type "exit"
19
+ Then the output should contain:
20
+ """
21
+ Using key abc
22
+ """
23
+
24
+ Scenario: Seeing a list of emitters
25
+ When I run `carbon` interactively
26
+ And I type "help"
27
+ And I type "exit"
28
+ Then the output should contain:
29
+ """
30
+ Computation
31
+ """
32
+
33
+ Scenario: Getting a calculation
34
+ When I run `carbon` interactively
35
+ And I type "computation"
36
+ And I type "done"
37
+ And I type "exit"
38
+ Then the output should contain:
39
+ """
40
+ kg CO2e
41
+ """
42
+
43
+ Scenario: Seeing a list of characteristics
44
+ When I run `carbon` interactively
45
+ And I type "computation"
46
+ And I type "help"
47
+ And I type "done"
48
+ And I type "exit"
49
+ Then the output should contain:
50
+ """
51
+ duration
52
+ """
53
+
54
+ Scenario: Setting a characteristic
55
+ When I run `carbon` interactively
56
+ And I type "computation"
57
+ And I type "duration 10"
58
+ And I type "done"
59
+ And I type "exit"
60
+ Then the output should contain:
61
+ """
62
+ kg CO2e
63
+ """
64
+
65
+ Scenario: Retrieving the default timeframe
66
+ When I run `carbon` interactively
67
+ And I type "computation"
68
+ And I type "timeframe"
69
+ And I type "done"
70
+ And I type "exit"
71
+ Then the output should contain:
72
+ """
73
+ (defaults to current year)
74
+ """
75
+
76
+ Scenario: Setting the timeframe
77
+ When I run `carbon` interactively
78
+ And I type "computation"
79
+ And I type "timeframe '2009'"
80
+ And I type "timeframe"
81
+ And I type "done"
82
+ And I type "exit"
83
+ Then the output should contain:
84
+ """
85
+ => 2009
86
+ """
87
+
88
+ Scenario: Getting the current emission
89
+ When I run `carbon` interactively
90
+ And I type "computation"
91
+ And I type "emission"
92
+ And I type "done"
93
+ And I type "exit"
94
+ Then the output should contain:
95
+ """
96
+ kg CO2e
97
+ """
98
+
99
+ Scenario: Using a different unit
100
+ When I run `carbon` interactively
101
+ And I type "computation"
102
+ And I type "lbs"
103
+ And I type "done"
104
+ And I type "exit"
105
+ Then the output should contain:
106
+ """
107
+ lbs CO2e
108
+ """
109
+
110
+ Scenario: Retrieving default characteristics
111
+ When I run `carbon` interactively
112
+ And I type "computation"
113
+ And I type "characteristics"
114
+ And I type "done"
115
+ And I type "exit"
116
+ Then the output should contain:
117
+ """
118
+ (none)
119
+ """
120
+
121
+ Scenario: Retrieving set characteristics
122
+ When I run `carbon` interactively
123
+ And I type "computation"
124
+ And I type "duration 10; characteristics; done"
125
+ And I type "exit"
126
+ Then the output should contain:
127
+ """
128
+ duration: 10
129
+ """
130
+
131
+ Scenario: Retrieving default methodology
132
+ When I run `carbon` interactively
133
+ And I type "computation"
134
+ And I type "methodology"
135
+ And I type "done"
136
+ And I type "exit"
137
+ Then the output should contain:
138
+ """
139
+ duration: default
140
+ """
141
+
142
+ Scenario: Retrieving customized methodology
143
+ When I run `carbon` interactively
144
+ And I type "computation"
145
+ And I type "duration 10; methodology; done"
146
+ And I type "exit"
147
+ Then the output should not contain:
148
+ """
149
+ duration:
150
+ """
151
+
152
+ Scenario: Retrieving reports
153
+ When I run `carbon` interactively
154
+ And I type "computation"
155
+ And I type "reports"
156
+ And I type "done"
157
+ And I type "exit"
158
+ Then the output should contain:
159
+ """
160
+ power_usage_effectiveness: 1.5
161
+ """
162
+
163
+ Scenario: Retrieving methodology URL
164
+ When I run `carbon` interactively
165
+ And I type "computation"
166
+ And I type "duration 10"
167
+ And I type "url"
168
+ And I type "done"
169
+ And I type "exit"
170
+ Then the output should contain:
171
+ """
172
+ http://carbon.brighterplanet.com/computations.json?duration=10
173
+ """
174
+
175
+ Scenario: Retrieving stored emitter
176
+ When I run `carbon` interactively
177
+ And I type "computation"
178
+ And I type "duration 10; done"
179
+ And I type "computation 0; characteristics; done"
180
+ And I type "exit"
181
+ Then the output should not contain:
182
+ """
183
+ duration: 10
184
+ """
185
+
186
+
@@ -0,0 +1,12 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
2
+ require 'aruba/cucumber'
3
+ require 'fileutils'
4
+ require 'rspec/expectations'
5
+ require 'carbon'
6
+ require 'conversions'
7
+
8
+ Before do
9
+ @aruba_io_wait_seconds = 2
10
+ @aruba_timeout_seconds = 5
11
+ @dirs = [File.join(ENV['HOME'], 'carbon_features')]
12
+ end
data/lib/carbon.rb CHANGED
@@ -11,13 +11,16 @@ require 'active_support/version'
11
11
  active_support/core_ext/hash/keys
12
12
  active_support/core_ext/hash/reverse_merge
13
13
  active_support/core_ext/object/to_query
14
+ active_support/inflector
14
15
  active_support/inflector/inflections
15
16
  active_support/json/decoding
16
17
  }.each do |active_support_3_requirement|
17
18
  require active_support_3_requirement
18
19
  end if ActiveSupport::VERSION::MAJOR == 3
20
+
19
21
  require 'carbon/base'
20
22
  require 'carbon/emission_estimate'
23
+ require 'logger'
21
24
 
22
25
  # A module (aka mixin) that lets you estimate carbon emissions by querying the {Brighter Planet carbon middleware emission estimate web service}[http://carbon.brighterplanet.com].
23
26
  #
@@ -44,10 +47,6 @@ module Carbon
44
47
  klass.extend ClassMethods
45
48
  end
46
49
 
47
- REALTIME_URL = 'http://carbon.brighterplanet.com'
48
- ASYNC_URL = 'https://queue.amazonaws.com/121562143717/cm1_production_incoming'
49
- STORAGE_URL = 'http://storage.carbon.brighterplanet.com'
50
-
51
50
  class RealtimeEstimateFailed < RuntimeError # :nodoc:
52
51
  end
53
52
  class QueueingFailed < RuntimeError # :nodoc:
@@ -59,6 +58,16 @@ module Carbon
59
58
 
60
59
  # The api key obtained from http://keys.brighterplanet.com
61
60
  mattr_accessor :key
61
+
62
+ mattr_accessor :log
63
+
64
+ def self.log #:nodoc:
65
+ @log ||= Logger.new STDOUT
66
+ end
67
+
68
+ def self.warn(msg) #:nodoc:
69
+ log.warn msg
70
+ end
62
71
 
63
72
  # You will probably never access this module directly. Instead, you'll use it through the DSL.
64
73
  #
data/lib/carbon/base.rb CHANGED
@@ -6,6 +6,7 @@ module Carbon
6
6
  include Blockenspiel::DSL
7
7
  attr_reader :klass
8
8
  attr_reader :emitter_common_name
9
+
9
10
  def initialize(klass, emitter_common_name)
10
11
  @klass = klass
11
12
  @emitter_common_name = emitter_common_name.to_s
@@ -21,7 +22,7 @@ module Carbon
21
22
  @translation_table ||= Hash.new
22
23
  end
23
24
 
24
- def reset_translation_table!
25
+ def reset_translation_table! #:nodoc:
25
26
  @translation_table = Hash.new
26
27
  end
27
28
 
@@ -11,10 +11,10 @@ module Carbon
11
11
  #
12
12
  # At the same time, they contain all the data you get back from the emission estimate web service. For example, you could say <tt>puts my_donut_factor.emission_estimate.oven_count</tt> (see the tests) and you'd get back the oven count used in the calculation, if any.
13
13
  class EmissionEstimate
14
- def self.parse(str)
14
+ def self.parse(str) #:nodoc:
15
15
  data = ::ActiveSupport::JSON.decode str
16
16
  data['active_subtimeframe'] = ::Timeframe.interval(data['active_subtimeframe']) if data.has_key? 'active_subtimeframe'
17
- data['updated_at'] = ::Time.parse(data['updated_at']) if data.has_key? 'updated_at'
17
+ data['updated_at'] = ::Time.parse(data['updated_at']) if data.has_key?('updated_at') and data['updated_at'].is_a?(::String)
18
18
  data
19
19
  end
20
20
 
@@ -24,6 +24,7 @@ module Carbon
24
24
  attr_writer :defer
25
25
  attr_accessor :callback
26
26
  attr_accessor :timeframe
27
+ attr_accessor :certified
27
28
  attr_accessor :guid
28
29
  attr_reader :emitter
29
30
 
@@ -32,8 +33,9 @@ module Carbon
32
33
  take_options options unless options.empty?
33
34
  end
34
35
 
35
- VALID_OPTIONS = [:callback_content_type, :key, :callback, :timeframe, :guid, :timeout, :defer]
36
- def take_options(options)
36
+ VALID_OPTIONS = [:callback_content_type, :key, :callback, :timeframe, :guid, :timeout, :defer, :certified]
37
+
38
+ def take_options(options) #:nodoc:
37
39
  return if options.blank?
38
40
  options.slice(*VALID_OPTIONS).each do |k, v|
39
41
  instance_variable_set "@#{k}", v
@@ -66,7 +68,7 @@ module Carbon
66
68
  end
67
69
  end
68
70
 
69
- def data
71
+ def data #:nodoc:
70
72
  if storage.present?
71
73
  storage.data
72
74
  else
@@ -74,18 +76,18 @@ module Carbon
74
76
  end
75
77
  end
76
78
 
77
- def storage
79
+ def storage #:nodoc:
78
80
  @storage ||= {}
79
81
  return @storage[guid] if @storage.has_key? guid
80
82
  @storage[guid] = Storage.new self
81
83
  end
82
84
 
83
- def request
85
+ def request #:nodoc:
84
86
  @request ||= Request.new self
85
87
  end
86
88
 
87
89
  # Here's where caching takes place.
88
- def response
90
+ def response #:nodoc:
89
91
  current_params = request.params
90
92
  @response ||= {}
91
93
  return @response[current_params] if @response.has_key? current_params
@@ -94,15 +96,19 @@ module Carbon
94
96
  @response[current_params] = response_object
95
97
  end
96
98
 
97
- def defer?
99
+ def certified? #:nodoc:
100
+ !!certified
101
+ end
102
+
103
+ def defer? #:nodoc:
98
104
  @defer == true
99
105
  end
100
106
 
101
- def async?
107
+ def async? #:nodoc:
102
108
  callback or defer?
103
109
  end
104
110
 
105
- def mode
111
+ def mode #:nodoc:
106
112
  async? ? :async : :realtime
107
113
  end
108
114
 
@@ -1,6 +1,6 @@
1
1
  module Carbon
2
2
  class EmissionEstimate
3
- class Request
3
+ class Request #:nodoc:all
4
4
  attr_reader :parent
5
5
 
6
6
  def initialize(parent)
@@ -12,10 +12,18 @@ module Carbon
12
12
  end
13
13
 
14
14
  def params
15
- send "#{parent.mode}_params"
15
+ params = send "#{parent.mode}_params"
16
+ validate params
17
+ params
16
18
  end
17
19
 
18
- def async_params # :nodoc:
20
+ def validate(params_hash)
21
+ unless params_hash.key? :key
22
+ Carbon.warn 'You have not specified an API key. Please obtain a key from http://keys.brighterplanet.com.'
23
+ end
24
+ end
25
+
26
+ def async_params
19
27
  raise ::ArgumentError, "When using :callback you cannot specify :defer" if parent.defer? and parent.callback
20
28
  raise ::ArgumentError, "When using :defer => true you must specify :guid" if parent.defer? and parent.guid.blank?
21
29
  hash = _params
@@ -30,7 +38,7 @@ module Carbon
30
38
  }
31
39
  end
32
40
 
33
- def realtime_params # :nodoc:
41
+ def realtime_params
34
42
  _params
35
43
  end
36
44
 
@@ -67,12 +75,20 @@ module Carbon
67
75
  hash
68
76
  end
69
77
 
70
- def realtime_url # :nodoc:
71
- "#{::Carbon::REALTIME_URL}/#{parent.emitter.class.carbon_base.emitter_common_name.pluralize}.json"
78
+ def realtime_url
79
+ uri = ::URI.parse ''
80
+ uri.scheme = 'http'
81
+ uri.host = parent.certified? ? 'certified.carbon.brighterplanet.com' : 'carbon.brighterplanet.com'
82
+ uri.path = "/#{parent.emitter.class.carbon_base.emitter_common_name.pluralize}.json"
83
+ uri.to_s
72
84
  end
73
85
 
74
- def async_url # :nodoc:
75
- ::Carbon::ASYNC_URL
86
+ def async_url
87
+ uri = ::URI.parse ''
88
+ uri.scheme = 'https'
89
+ uri.host = 'queue.amazonaws.com'
90
+ uri.path = parent.certified? ? '/121562143717/cm1_production_incoming_certified' : '/121562143717/cm1_production_incoming'
91
+ uri.to_s
76
92
  end
77
93
 
78
94
  def url
@@ -1,6 +1,6 @@
1
1
  module Carbon
2
2
  class EmissionEstimate
3
- class Response
3
+ class Response #:nodoc:all
4
4
  attr_reader :parent
5
5
  attr_reader :data
6
6
  attr_reader :raw_request
@@ -15,7 +15,7 @@ module Carbon
15
15
  end
16
16
 
17
17
  private
18
- def load_realtime_data # :nodoc:
18
+ def load_realtime_data
19
19
  attempts = 0
20
20
  response = nil
21
21
  begin
@@ -34,13 +34,13 @@ module Carbon
34
34
  @data = ::Carbon::EmissionEstimate.parse response.body
35
35
  end
36
36
 
37
- def load_async_data # :nodoc:
37
+ def load_async_data
38
38
  response = perform
39
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.
40
40
  @data = {}
41
41
  end
42
42
 
43
- def perform # :nodoc:
43
+ def perform
44
44
  response = nil
45
45
  if parent.timeout
46
46
  Timeout.timeout(parent.timeout) do
@@ -52,7 +52,7 @@ module Carbon
52
52
  response
53
53
  end
54
54
 
55
- def perform_request # :nodoc:
55
+ def perform_request
56
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'}
57
57
  @raw_response = raw_request.perform
58
58
  end
@@ -1,6 +1,6 @@
1
1
  module Carbon
2
2
  class EmissionEstimate
3
- class Storage
3
+ class Storage #:nodoc:all
4
4
  attr_accessor :parent
5
5
  attr_reader :raw_request
6
6
  attr_reader :raw_response
@@ -10,7 +10,7 @@ module Carbon
10
10
  end
11
11
 
12
12
  def url
13
- "#{::Carbon::STORAGE_URL}/#{::Digest::SHA1.hexdigest(parent.key+parent.guid)}"
13
+ "http://storage.carbon.brighterplanet.com/#{::Digest::SHA1.hexdigest(parent.key+parent.guid)}"
14
14
  end
15
15
 
16
16
  def present?
@@ -0,0 +1,51 @@
1
+ require 'brighter_planet_metadata'
2
+ require 'bombshell'
3
+ require 'conversions'
4
+ module Carbon
5
+ class Shell < Bombshell::Environment
6
+ include Bombshell::Shell
7
+
8
+ before_launch do
9
+ $emitters = {}
10
+ emitters.map(&:underscore).each do |e|
11
+ define_method e.to_sym do |*args|
12
+ if args.any? and num = args.first and saved = $emitters[e.to_sym][num]
13
+ emitter e.to_sym, saved
14
+ else
15
+ emitter e.to_sym
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ prompt_with 'carbon-'
22
+
23
+ def help
24
+ puts " => #{self.class.emitters.join ', '}"
25
+ end
26
+
27
+ def key(k)
28
+ ::Carbon.key = k
29
+ puts " => Using key #{::Carbon.key}"
30
+ end
31
+
32
+ def emitter(e, saved = {})
33
+ Emitter.launch e, saved
34
+ end
35
+
36
+ class << self
37
+ def emitters
38
+ ::BrighterPlanet.metadata.emitters
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ if File.exist?(dotfile = File.join(ENV['HOME'], '.brighter_planet'))
45
+ if (key = File.read(dotfile).strip).present?
46
+ ::Carbon.key = key
47
+ end
48
+ end
49
+
50
+ require 'carbon/shell/emitter'
51
+
@@ -1,7 +1,9 @@
1
1
  module Carbon
2
- module Cli
3
- class Emitter < Environment
2
+ class Shell
3
+ class Emitter < Bombshell::Environment
4
+ include Bombshell::Shell
4
5
  include Carbon
6
+
5
7
  def initialize(name, input = {})
6
8
  @emitter = name
7
9
  @input = input
@@ -38,8 +40,10 @@ module Carbon
38
40
  if t
39
41
  @timeframe = t
40
42
  emission
43
+ elsif @timeframe
44
+ puts ' => ' + @timeframe
41
45
  else
42
- @timeframe
46
+ puts ' => (defaults to current year)'
43
47
  end
44
48
  end
45
49
 
@@ -116,8 +120,20 @@ module Carbon
116
120
  puts " => #{@characteristics.keys.join ', '}"
117
121
  end
118
122
 
119
- def to_s
120
- "#{@emitter}*"
123
+ prompt_with do |emitter|
124
+ if emitter._timeframe
125
+ "#{emitter._name}[#{emitter._timeframe}]*"
126
+ else
127
+ "#{emitter._name}*"
128
+ end
129
+ end
130
+
131
+ def _name
132
+ @emitter
133
+ end
134
+
135
+ def _timeframe
136
+ @timeframe
121
137
  end
122
138
 
123
139
  def inspect
@@ -128,7 +144,13 @@ module Carbon
128
144
  $emitters[@emitter] ||= []
129
145
  $emitters[@emitter] << @input
130
146
  puts " => Saved as #{@emitter} ##{$emitters[@emitter].length - 1}"
131
- throw :IRB_EXIT
147
+ quit
148
+ end
149
+
150
+ class << self
151
+ def emitter_name
152
+ @name
153
+ end
132
154
  end
133
155
  end
134
156
  end
@@ -1,3 +1,3 @@
1
1
  module Carbon
2
- VERSION = '1.0.4'
2
+ VERSION = '1.1.0'
3
3
  end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe Carbon::EmissionEstimate::Request do
4
+ let(:emitter) do
5
+ mock Object,
6
+ :class => mock(Object,
7
+ :carbon_base => mock(Object,
8
+ :emitter_common_name => 'dirigible',
9
+ :translation_table => []))
10
+ end
11
+ let(:emission_estimate) { Carbon::EmissionEstimate.new emitter }
12
+ let(:request) { Carbon::EmissionEstimate::Request.new emission_estimate }
13
+
14
+ describe '#params' do
15
+ it 'returns a hash of params' do
16
+ request.params.should be_a_kind_of(Hash)
17
+ end
18
+ it 'validates the params' do
19
+ request.should_receive :validate
20
+ request.params
21
+ end
22
+ end
23
+
24
+ describe '#validate' do
25
+ it 'warns the user if no key is given' do
26
+ Carbon.should_receive :warn
27
+ request.validate({})
28
+ end
29
+ it 'does nothing if all parameters are OK' do
30
+ Carbon.should_not_receive :warn
31
+ request.validate(
32
+ :key => 'ABC123'
33
+ )
34
+ end
35
+ end
36
+ end
37
+
@@ -7,7 +7,7 @@ MISSING_UNIQUE_ID = 'd09joijdoijaloijdoais'
7
7
  OTHER_UNIQUE_ID = '1092fjoid;oijsao;ga'
8
8
 
9
9
  FakeWeb.register_uri :post,
10
- /carbon.brighterplanet.com.automobiles/,
10
+ %r{http://carbon.brighterplanet.com/automobile_trips},
11
11
  :status => ["200", "OK"],
12
12
  :body => {
13
13
  'emission' => '134.599',
@@ -16,6 +16,16 @@ FakeWeb.register_uri :post,
16
16
  'active_subtimeframe' => Timeframe.new(:year => 2008)
17
17
  }.to_json
18
18
  #
19
+ FakeWeb.register_uri :post,
20
+ %r{http://certified.carbon.brighterplanet.com/automobile_trips},
21
+ :status => ["200", "OK"],
22
+ :body => {
23
+ 'emission' => '54321',
24
+ 'emission_units' => 'kilograms',
25
+ 'methodology' => 'http://certified.carbon.brighterplanet.com/something',
26
+ 'active_subtimeframe' => Timeframe.new(:year => 2008)
27
+ }.to_json
28
+ #
19
29
  FakeWeb.register_uri :post,
20
30
  /carbon.brighterplanet.com.factories/,
21
31
  :status => ["200", "OK"],
@@ -91,7 +101,7 @@ class RentalCar
91
101
  def make
92
102
  @make ||= Make.new
93
103
  end
94
- emit_as :automobile do
104
+ emit_as :automobile_trip do
95
105
  provide :make
96
106
  provide :model
97
107
  provide :model_year
@@ -313,6 +323,17 @@ describe Carbon do
313
323
  c.emission_estimate.request.body.should_not include('&&')
314
324
  c.emission_estimate.request.body.should_not =~ /=[^a-z0-9]/i
315
325
  end
326
+
327
+ it 'should do certified calculations' do
328
+ c = RentalCar.new
329
+ c.emission_estimate.certified = true
330
+ c.emission_estimate.should == 54321
331
+ end
332
+
333
+ it 'should do certified calculations (inline)' do
334
+ c = RentalCar.new
335
+ c.emission_estimate(:certified => true).should == 54321
336
+ end
316
337
  end
317
338
 
318
339
  describe 'asynchronous (queued) requests' do
@@ -322,6 +343,19 @@ describe Carbon do
322
343
  c.emission_estimate.request.url.should =~ /queue.amazonaws.com/
323
344
  end
324
345
 
346
+ it 'should default to non-certified' do
347
+ c = RentalCar.new
348
+ c.emission_estimate.callback = CALLBACK_URL
349
+ c.emission_estimate.request.url.should_not =~ /certified/
350
+ end
351
+
352
+ it 'should accept certified' do
353
+ c = RentalCar.new
354
+ c.emission_estimate.callback = CALLBACK_URL
355
+ c.emission_estimate.certified = true
356
+ c.emission_estimate.request.url.should =~ /certified/
357
+ end
358
+
325
359
  it 'should have nil data in its response' do
326
360
  c = RentalCar.new
327
361
  c.emission_estimate.callback = CALLBACK_URL
data/spec/spec_helper.rb CHANGED
@@ -7,3 +7,5 @@ require 'fakeweb'
7
7
  $LOAD_PATH.unshift(File.dirname(__FILE__))
8
8
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
9
9
  require 'carbon'
10
+
11
+ Carbon.log = Logger.new nil
metadata CHANGED
@@ -1,13 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: carbon
3
3
  version: !ruby/object:Gem::Version
4
- hash: 31
5
- prerelease: false
6
- segments:
7
- - 1
8
- - 0
9
- - 4
10
- version: 1.0.4
4
+ prerelease:
5
+ version: 1.1.0
11
6
  platform: ruby
12
7
  authors:
13
8
  - Derek Kastner
@@ -17,7 +12,7 @@ autorequire:
17
12
  bindir: bin
18
13
  cert_chain: []
19
14
 
20
- date: 2011-02-03 00:00:00 -06:00
15
+ date: 2011-04-04 00:00:00 -05:00
21
16
  default_executable:
22
17
  dependencies:
23
18
  - !ruby/object:Gem::Dependency
@@ -28,11 +23,6 @@ dependencies:
28
23
  requirements:
29
24
  - - ">="
30
25
  - !ruby/object:Gem::Version
31
- hash: 9
32
- segments:
33
- - 2
34
- - 3
35
- - 5
36
26
  version: 2.3.5
37
27
  type: :runtime
38
28
  version_requirements: *id001
@@ -44,9 +34,6 @@ dependencies:
44
34
  requirements:
45
35
  - - ">="
46
36
  - !ruby/object:Gem::Version
47
- hash: 3
48
- segments:
49
- - 0
50
37
  version: "0"
51
38
  type: :runtime
52
39
  version_requirements: *id002
@@ -58,9 +45,6 @@ dependencies:
58
45
  requirements:
59
46
  - - ">="
60
47
  - !ruby/object:Gem::Version
61
- hash: 3
62
- segments:
63
- - 0
64
48
  version: "0"
65
49
  type: :runtime
66
50
  version_requirements: *id003
@@ -72,9 +56,6 @@ dependencies:
72
56
  requirements:
73
57
  - - ">="
74
58
  - !ruby/object:Gem::Version
75
- hash: 3
76
- segments:
77
- - 0
78
59
  version: "0"
79
60
  type: :runtime
80
61
  version_requirements: *id004
@@ -86,9 +67,6 @@ dependencies:
86
67
  requirements:
87
68
  - - ">="
88
69
  - !ruby/object:Gem::Version
89
- hash: 3
90
- segments:
91
- - 0
92
70
  version: "0"
93
71
  type: :runtime
94
72
  version_requirements: *id005
@@ -100,40 +78,64 @@ dependencies:
100
78
  requirements:
101
79
  - - ">="
102
80
  - !ruby/object:Gem::Version
103
- hash: 3
104
- segments:
105
- - 0
106
81
  version: "0"
107
82
  type: :runtime
108
83
  version_requirements: *id006
109
84
  - !ruby/object:Gem::Dependency
110
- name: fakeweb
85
+ name: brighter_planet_metadata
111
86
  prerelease: false
112
87
  requirement: &id007 !ruby/object:Gem::Requirement
113
88
  none: false
114
89
  requirements:
115
90
  - - ">="
116
91
  - !ruby/object:Gem::Version
117
- hash: 3
118
- segments:
119
- - 0
120
92
  version: "0"
121
- type: :development
93
+ type: :runtime
122
94
  version_requirements: *id007
123
95
  - !ruby/object:Gem::Dependency
124
- name: rspec
96
+ name: bombshell
125
97
  prerelease: false
126
98
  requirement: &id008 !ruby/object:Gem::Requirement
127
99
  none: false
128
100
  requirements:
129
101
  - - ">="
130
102
  - !ruby/object:Gem::Version
131
- hash: 3
132
- segments:
133
- - 0
134
103
  version: "0"
135
- type: :development
104
+ type: :runtime
136
105
  version_requirements: *id008
106
+ - !ruby/object:Gem::Dependency
107
+ name: fakeweb
108
+ prerelease: false
109
+ requirement: &id009 !ruby/object:Gem::Requirement
110
+ none: false
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: "0"
115
+ type: :development
116
+ version_requirements: *id009
117
+ - !ruby/object:Gem::Dependency
118
+ name: rspec
119
+ prerelease: false
120
+ requirement: &id010 !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: "0"
126
+ type: :development
127
+ version_requirements: *id010
128
+ - !ruby/object:Gem::Dependency
129
+ name: aruba
130
+ prerelease: false
131
+ requirement: &id011 !ruby/object:Gem::Requirement
132
+ none: false
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: "0"
137
+ type: :development
138
+ version_requirements: *id011
137
139
  description: 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.
138
140
  email:
139
141
  - derek.kastner@brighterplanet.com
@@ -157,19 +159,18 @@ files:
157
159
  - doc/timeout-error.png
158
160
  - doc/with-committee-reports.png
159
161
  - doc/without-committee-reports.png
162
+ - features/shell.feature
163
+ - features/support/env.rb
160
164
  - lib/carbon.rb
161
165
  - lib/carbon/base.rb
162
- - lib/carbon/cli.rb
163
- - lib/carbon/cli/emitter.rb
164
- - lib/carbon/cli/environment.rb
165
- - lib/carbon/cli/irb.rb
166
- - lib/carbon/cli/shell.rb
167
166
  - lib/carbon/emission_estimate.rb
168
167
  - lib/carbon/emission_estimate/request.rb
169
168
  - lib/carbon/emission_estimate/response.rb
170
169
  - lib/carbon/emission_estimate/storage.rb
170
+ - lib/carbon/shell.rb
171
+ - lib/carbon/shell/emitter.rb
171
172
  - lib/carbon/version.rb
172
- - spec/lib/carbon/cli/shell_spec.rb
173
+ - spec/lib/carbon/emission_estimate/request_spec.rb
173
174
  - spec/lib/carbon/emission_estimate/response_spec.rb
174
175
  - spec/lib/carbon_spec.rb
175
176
  - spec/spec_helper.rb
@@ -188,28 +189,24 @@ required_ruby_version: !ruby/object:Gem::Requirement
188
189
  requirements:
189
190
  - - ">="
190
191
  - !ruby/object:Gem::Version
191
- hash: 3
192
- segments:
193
- - 0
194
192
  version: "0"
195
193
  required_rubygems_version: !ruby/object:Gem::Requirement
196
194
  none: false
197
195
  requirements:
198
196
  - - ">="
199
197
  - !ruby/object:Gem::Version
200
- hash: 3
201
- segments:
202
- - 0
203
198
  version: "0"
204
199
  requirements: []
205
200
 
206
201
  rubyforge_project: carbon
207
- rubygems_version: 1.3.7
202
+ rubygems_version: 1.6.2
208
203
  signing_key:
209
204
  specification_version: 3
210
205
  summary: Carbon is a Ruby API wrapper for the Brighter Planet emission estimate web service (http://carbon.brighterplanet.com).
211
206
  test_files:
212
- - spec/lib/carbon/cli/shell_spec.rb
207
+ - features/shell.feature
208
+ - features/support/env.rb
209
+ - spec/lib/carbon/emission_estimate/request_spec.rb
213
210
  - spec/lib/carbon/emission_estimate/response_spec.rb
214
211
  - spec/lib/carbon_spec.rb
215
212
  - spec/spec_helper.rb
data/lib/carbon/cli.rb DELETED
@@ -1,22 +0,0 @@
1
- module Carbon
2
- module Cli
3
- def execute(*)
4
- Shell.init
5
- $emitters = {}
6
- IRB.start_session(Shell.new.get_binding)
7
- end
8
- module_function :execute
9
- end
10
- end
11
-
12
- require 'carbon/cli/environment'
13
- require 'carbon/cli/shell'
14
- require 'carbon/cli/emitter'
15
- require 'carbon/cli/irb'
16
- require 'conversions'
17
-
18
- if File.exist?(dotfile = File.join(ENV['HOME'], '.carbon_middleware'))
19
- if (key = File.read(dotfile).strip).present?
20
- ::Carbon.key = key
21
- end
22
- end
@@ -1,16 +0,0 @@
1
- module Carbon
2
- module Cli
3
- class Environment
4
- instance_methods.each do |m|
5
- undef_method(m) if m.to_s !~ /(?:^__|^nil\?$|^send$|^instance_eval$|^define_method$|^class$|^object_id$)/
6
- end
7
-
8
- def get_binding() binding end
9
-
10
- def method_missing(*args)
11
- return if [:extend, :respond_to?].include? args.first
12
- puts "Unknown command #{args.first}"
13
- end
14
- end
15
- end
16
- end
@@ -1,34 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'irb'
4
-
5
- module IRB # :nodoc:
6
- def self.start_session(binding)
7
- unless @__initialized
8
- args = ARGV
9
- ARGV.replace(ARGV.dup)
10
- IRB.setup(nil)
11
- ARGV.replace(args)
12
- @__initialized = true
13
- end
14
-
15
- workspace = WorkSpace.new(binding)
16
-
17
- @CONF[:PROMPT][:CARBON] = {
18
- :PROMPT_I => "%m> ",
19
- :PROMPT_S => "%m\"> ",
20
- :PROMPT_C => "%m…>",
21
- :PROMPT_N => "%m→>",
22
- :RETURN => ''
23
- }
24
- @CONF[:PROMPT_MODE] = :CARBON
25
-
26
- irb = Irb.new(workspace)
27
-
28
- @CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC]
29
- @CONF[:MAIN_CONTEXT] = irb.context
30
- catch(:IRB_EXIT) do
31
- irb.eval_input
32
- end
33
- end
34
- end
@@ -1,46 +0,0 @@
1
- require 'carbon/cli/environment'
2
-
3
- module Carbon
4
- module Cli
5
- class Shell < Environment
6
- cattr_accessor :emitters
7
-
8
- def self.init
9
- emitters_url = "http://carbon.brighterplanet.com/models.json"
10
- response = REST.get(emitters_url)
11
- if true || response.ok?
12
- self.emitters = ActiveSupport::JSON.decode response.body
13
- emitters.map(&:underscore).each do |e|
14
- define_method e.to_sym do |*args|
15
- if args.any? and num = args.first and saved = $emitters[e.to_sym][num]
16
- emitter e.to_sym, saved
17
- else
18
- emitter e.to_sym
19
- end
20
- end
21
- end
22
- else
23
- puts " => Sorry, emitter types couldn't be retrieved (via #{emitters_url})"
24
- done
25
- end
26
- end
27
-
28
- def help
29
- puts " => #{self.class.emitters.join ', '}"
30
- end
31
-
32
- def to_s
33
- 'carbon-'
34
- end
35
-
36
- def key(k)
37
- ::Carbon.key = k
38
- puts " => Using key #{::Carbon.key}"
39
- end
40
-
41
- def emitter(e, saved = {})
42
- ::IRB.start_session(Emitter.new(e, saved).get_binding)
43
- end
44
- end
45
- end
46
- end
@@ -1,30 +0,0 @@
1
- require 'spec_helper'
2
- require 'carbon/cli/shell'
3
-
4
- describe Carbon::Cli::Shell do
5
- let(:json) { %{
6
- ["Automobile","AutomobileTrip","BusTrip","Computation","Diet","Flight","FuelPurchase","Lodging","Meeting","Motorcycle","Pet","Purchase","RailTrip","Residence"]
7
- } }
8
- let(:mock_response) { mock(REST, :ok? => true, :body => json) }
9
- let(:shell) { Carbon::Cli::Shell.new }
10
-
11
-
12
- before(:each) do
13
- REST.stub!(:get).and_return mock_response
14
- end
15
-
16
- describe '.init' do
17
- it 'should create methods for each model' do
18
- Carbon::Cli::Shell.init
19
- Carbon::Cli::Shell.instance_methods.should include('automobile')
20
- end
21
- it 'should exit if the models cannot be fetched' do
22
- pending
23
-
24
- mock_response.stub!(:ok?).and_return false
25
- Carbon::Cli::Shell.should_receive :done
26
- Carbon::Cli::Shell.init
27
- end
28
- end
29
- end
30
-