carbon 0.1.6 → 0.2.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.rdoc +17 -11
- data/Rakefile +4 -3
- data/VERSION +1 -1
- data/carbon.gemspec +8 -5
- data/lib/carbon.rb +1 -4
- data/lib/carbon/base.rb +19 -15
- data/lib/carbon/emission_estimate/request.rb +16 -9
- data/spec/lib/carbon_spec.rb +45 -10
- metadata +27 -10
data/README.rdoc
CHANGED
@@ -6,35 +6,41 @@ By querying the web service, it can estimate the carbon emissions of many real-l
|
|
6
6
|
|
7
7
|
== Quick start
|
8
8
|
|
9
|
-
|
9
|
+
<b>You'll need a Brighter Planet API key. See the "API keys" section below for details.</b>
|
10
10
|
|
11
11
|
First get the gem:
|
12
12
|
|
13
13
|
$ gem install carbon
|
14
14
|
|
15
|
-
Carbon works by extending any Ruby class you're using to represent an emission source. For instance, let's say you have a Ruby class <tt>RentalCar</tt> that represents a rental car on your lot. (Note that ActiveRecord models work great with
|
15
|
+
Carbon works by extending any Ruby class you're using to represent an emission source. For instance, let's say you have a Ruby class <tt>RentalCar</tt> that represents a rental car on your lot. (Note that ActiveRecord models work great with this gem.)
|
16
16
|
|
17
17
|
class RentalCar
|
18
|
-
attr_accessor :
|
18
|
+
attr_accessor :model, :model_year, :fuel_economy
|
19
|
+
class Make
|
20
|
+
attr_accessor :name
|
21
|
+
def to_param
|
22
|
+
name
|
23
|
+
end
|
24
|
+
end
|
25
|
+
def make
|
26
|
+
@make ||= Make.new
|
27
|
+
end
|
19
28
|
end
|
20
29
|
|
21
30
|
In order to calculate carbon emissions, we need to map the car's relevant attributes to characteristics that the {web service}[http://carbon.brighterplanet.com] will recognize. In this case, a review of the available characteristics for Automobile[http://carbon.brighterplanet.com/automobiles/options] yields the following map:
|
22
31
|
|
23
32
|
class RentalCar
|
33
|
+
# [...]
|
24
34
|
include Carbon
|
25
|
-
[...]
|
26
35
|
emit_as :automobile do
|
27
|
-
provide :model_year, :as => :year # you say tomayto, I say tomahto
|
28
36
|
provide :make
|
29
37
|
provide :model
|
30
|
-
provide :
|
31
|
-
provide :
|
32
|
-
provide :acquisition, :as => :purchase_date
|
33
|
-
provide :retirement, :as => :retirement_date
|
38
|
+
provide :model_year
|
39
|
+
provide :fuel_economy, :as => :fuel_efficiency
|
34
40
|
end
|
35
41
|
end
|
36
42
|
|
37
|
-
When you want to calculate emissions, simply call <tt>RentalCar
|
43
|
+
When you want to calculate emissions, simply call <tt>RentalCar#emission</tt>.
|
38
44
|
|
39
45
|
> my_car = RentalCar.new([...])
|
40
46
|
=> #<RentalCar [...]>
|
@@ -49,7 +55,7 @@ When you want to calculate emissions, simply call <tt>RentalCar</tt>#<tt>emissio
|
|
49
55
|
|
50
56
|
=== Asynchronous queries
|
51
57
|
|
52
|
-
To request an emission estimate asynchronously, simply pass an URL as the
|
58
|
+
To request an emission estimate asynchronously, simply pass an URL as the <tt>:callback</tt> option to <tt>#emission</tt>:
|
53
59
|
|
54
60
|
> RentalCar.new.emission :callback => http://example.com/my/callback/handler
|
55
61
|
|
data/Rakefile
CHANGED
@@ -5,14 +5,15 @@ begin
|
|
5
5
|
require 'jeweler'
|
6
6
|
Jeweler::Tasks.new do |gemspec|
|
7
7
|
gemspec.name = 'carbon'
|
8
|
-
gemspec.summary = %q{
|
9
|
-
gemspec.description = %q{Carbon
|
8
|
+
gemspec.summary = %q{Carbon is a Ruby API wrapper for the Brighter Planet emission estimate web service (http://carbon.brighterplanet.com).}
|
9
|
+
gemspec.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.}
|
10
10
|
gemspec.email = 'derek.kastner@brighterplanet.com'
|
11
11
|
gemspec.homepage = 'http://carbon.brighterplanet.com/libraries'
|
12
|
-
gemspec.authors = ['Derek Kastner', 'Seamus Abshere']
|
12
|
+
gemspec.authors = ['Derek Kastner', 'Seamus Abshere', 'Andy Rossmeissl']
|
13
13
|
gemspec.add_dependency 'activesupport', '>=2.3.5'
|
14
14
|
gemspec.add_dependency 'nap', '>=0.4'
|
15
15
|
gemspec.add_dependency 'timeframe', '>=0.0.7'
|
16
|
+
gemspec.add_dependency 'blockenspiel', '>=0.3.2'
|
16
17
|
|
17
18
|
gemspec.add_development_dependency 'fakeweb', '>=1.2.8'
|
18
19
|
# sabshere 7/16/10 if you're having trouble running specs, try "rspec spec" and/or "sudo gem install rspec --pre"
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/carbon.gemspec
CHANGED
@@ -5,12 +5,12 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{carbon}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
-
s.authors = ["Derek Kastner", "Seamus Abshere"]
|
12
|
-
s.date = %q{2010-07-
|
13
|
-
s.description = %q{Carbon
|
11
|
+
s.authors = ["Derek Kastner", "Seamus Abshere", "Andy Rossmeissl"]
|
12
|
+
s.date = %q{2010-07-21}
|
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 = [
|
16
16
|
"README.rdoc"
|
@@ -35,7 +35,7 @@ Gem::Specification.new do |s|
|
|
35
35
|
s.rdoc_options = ["--charset=UTF-8"]
|
36
36
|
s.require_paths = ["lib"]
|
37
37
|
s.rubygems_version = %q{1.3.7}
|
38
|
-
s.summary = %q{
|
38
|
+
s.summary = %q{Carbon is a Ruby API wrapper for the Brighter Planet emission estimate web service (http://carbon.brighterplanet.com).}
|
39
39
|
s.test_files = [
|
40
40
|
"spec/lib/carbon_spec.rb",
|
41
41
|
"spec/spec_helper.rb"
|
@@ -49,12 +49,14 @@ Gem::Specification.new do |s|
|
|
49
49
|
s.add_runtime_dependency(%q<activesupport>, [">= 2.3.5"])
|
50
50
|
s.add_runtime_dependency(%q<nap>, [">= 0.4"])
|
51
51
|
s.add_runtime_dependency(%q<timeframe>, [">= 0.0.7"])
|
52
|
+
s.add_runtime_dependency(%q<blockenspiel>, [">= 0.3.2"])
|
52
53
|
s.add_development_dependency(%q<fakeweb>, [">= 1.2.8"])
|
53
54
|
s.add_development_dependency(%q<rspec>, [">= 2.0.0.beta.17"])
|
54
55
|
else
|
55
56
|
s.add_dependency(%q<activesupport>, [">= 2.3.5"])
|
56
57
|
s.add_dependency(%q<nap>, [">= 0.4"])
|
57
58
|
s.add_dependency(%q<timeframe>, [">= 0.0.7"])
|
59
|
+
s.add_dependency(%q<blockenspiel>, [">= 0.3.2"])
|
58
60
|
s.add_dependency(%q<fakeweb>, [">= 1.2.8"])
|
59
61
|
s.add_dependency(%q<rspec>, [">= 2.0.0.beta.17"])
|
60
62
|
end
|
@@ -62,6 +64,7 @@ Gem::Specification.new do |s|
|
|
62
64
|
s.add_dependency(%q<activesupport>, [">= 2.3.5"])
|
63
65
|
s.add_dependency(%q<nap>, [">= 0.4"])
|
64
66
|
s.add_dependency(%q<timeframe>, [">= 0.0.7"])
|
67
|
+
s.add_dependency(%q<blockenspiel>, [">= 0.3.2"])
|
65
68
|
s.add_dependency(%q<fakeweb>, [">= 1.2.8"])
|
66
69
|
s.add_dependency(%q<rspec>, [">= 2.0.0.beta.17"])
|
67
70
|
end
|
data/lib/carbon.rb
CHANGED
@@ -9,7 +9,6 @@ require 'active_support/version'
|
|
9
9
|
active_support/core_ext/hash/keys
|
10
10
|
active_support/core_ext/hash/reverse_merge
|
11
11
|
active_support/core_ext/object/to_query
|
12
|
-
active_support/core_ext/array/wrap
|
13
12
|
active_support/inflector/inflections
|
14
13
|
active_support/json/decoding
|
15
14
|
}.each do |active_support_3_requirement|
|
@@ -78,9 +77,7 @@ module Carbon
|
|
78
77
|
|
79
78
|
# Returns an emission estimate.
|
80
79
|
#
|
81
|
-
# Note:
|
82
|
-
#
|
83
|
-
# Note also: please see the README about exceptions that you should watch out for.
|
80
|
+
# Note: please see the README about <b>exceptions that you should watch out for</b>.
|
84
81
|
#
|
85
82
|
# You can use it like a number...
|
86
83
|
# > my_car.emission + 5.1
|
data/lib/carbon/base.rb
CHANGED
@@ -21,30 +21,34 @@ module Carbon
|
|
21
21
|
end
|
22
22
|
# Indicate that you will send in a piece of data about the emitter.
|
23
23
|
#
|
24
|
-
#
|
24
|
+
# Two general rules:
|
25
|
+
# * Take note of what Brighter Planet expects to receive. If you send <tt>fuel_economy</tt> and we're expecting <tt>fuel_efficiency</tt>, we won't understand! (Hint: use the <tt>:as</tt> option.)
|
26
|
+
# * Make sure <tt>#to_param</tt> is set up. The gem always calls <tt>#to_param</tt> before sending, so that's your change to key things by "EPA code" (fictional) or whatever else you want. (Hint: use the <tt>:key</tt> option.)
|
25
27
|
#
|
26
28
|
# There are two optional parameters:
|
27
|
-
# * <tt>:
|
28
|
-
# * <tt>:
|
29
|
+
# * <tt>:as</tt> - if Brighter Planet expects <tt>fuel_efficiency</tt>, and you say <tt>mpg</tt>, you can write <tt>provide :mpg, :as => :fuel_efficiency</tt>. This will result in a query like <tt>?fuel_efficiency=XYZ</tt>.
|
30
|
+
# * <tt>:key</tt> - if Brighter Planet expects a make's name ("Nissan") and you want to look things up by (fictional) "EPA code", you could say <tt>provide :make, :key => :epa_code</tt>. This will result in a query like <tt>?make[epa_code]=ABC</tt>.
|
29
31
|
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
# provide :
|
32
|
+
# # What's sent to Brighter Planet
|
33
|
+
# emit_as :automobile do
|
34
|
+
# provide :mpg, :as => :fuel_efficiency # fuel_efficiency=my_car.mpg.to_param
|
35
|
+
# provide :make, :key => :epa_code # make[epa_code]=my_car.make.to_param
|
36
|
+
# # or really shaking things up...
|
37
|
+
# provide :manufacturer, :as => :make, :key => :epa_code # make[epa_code]=my_car.manufacturer.to_param
|
36
38
|
# end
|
39
|
+
#
|
40
|
+
# Note that no matter what you send to us, the gem always calls <b>to_param</b> on the emitter. In this example, it's up to you to make sure my_car.manufacturer.to_param returns an epa_code.
|
37
41
|
def provide(attr_name, options = {})
|
38
42
|
options = options.symbolize_keys
|
39
|
-
characteristic = if options.has_key? :
|
40
|
-
# [ :
|
41
|
-
[options[:
|
43
|
+
characteristic = if options.has_key? :as
|
44
|
+
# [ :mpg, :fuel_efficiency ]
|
45
|
+
[attr_name, options[:as]]
|
42
46
|
else
|
43
|
-
# :
|
47
|
+
# :make
|
44
48
|
attr_name
|
45
49
|
end
|
46
|
-
# translation_table[
|
47
|
-
translation_table[characteristic] = options[:
|
50
|
+
# translation_table[:make] = 'epa_code'
|
51
|
+
translation_table[characteristic] = options[:key]
|
48
52
|
end
|
49
53
|
# japanese-style preferred
|
50
54
|
alias :provides :provide
|
@@ -27,20 +27,27 @@ module Carbon
|
|
27
27
|
# Returns the params hash that will be send to the emission estimate server.
|
28
28
|
def params
|
29
29
|
params = parent.emitter.class.carbon_base.translation_table.inject({}) do |memo, translation|
|
30
|
-
characteristic,
|
31
|
-
|
30
|
+
characteristic, key = translation
|
31
|
+
if characteristic.is_a? ::Array
|
32
|
+
current_value = parent.emitter.send characteristic[0]
|
33
|
+
as = characteristic[1]
|
34
|
+
else
|
35
|
+
current_value = parent.emitter.send characteristic
|
36
|
+
as = characteristic
|
37
|
+
end
|
38
|
+
current_value = current_value.to_param
|
32
39
|
if current_value.present?
|
33
|
-
if
|
34
|
-
memo[
|
35
|
-
memo[
|
36
|
-
else
|
37
|
-
memo[
|
40
|
+
if key
|
41
|
+
memo[as] ||= {}
|
42
|
+
memo[as][key] = current_value
|
43
|
+
else
|
44
|
+
memo[as] = current_value
|
38
45
|
end
|
39
46
|
end
|
40
47
|
memo
|
41
48
|
end
|
42
|
-
params[:timeframe] = parent.timeframe
|
43
|
-
params[:key] = parent.key
|
49
|
+
params[:timeframe] = parent.timeframe if parent.timeframe
|
50
|
+
params[:key] = parent.key if parent.key
|
44
51
|
params
|
45
52
|
end
|
46
53
|
def realtime_url # :nodoc:
|
data/spec/lib/carbon_spec.rb
CHANGED
@@ -2,24 +2,41 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
class RentalCar
|
4
4
|
include Carbon
|
5
|
-
attr_accessor :
|
5
|
+
attr_accessor :model, :model_year, :fuel_economy
|
6
|
+
class Make
|
7
|
+
attr_accessor :name
|
8
|
+
def to_param
|
9
|
+
name
|
10
|
+
end
|
11
|
+
end
|
12
|
+
def make
|
13
|
+
@make ||= Make.new
|
14
|
+
end
|
6
15
|
emit_as :automobile do
|
7
16
|
provide :make
|
8
17
|
provide :model
|
9
18
|
provide :model_year
|
10
|
-
provide :
|
19
|
+
provide :fuel_economy, :as => :fuel_efficiency
|
11
20
|
end
|
12
21
|
end
|
13
22
|
|
14
23
|
class DonutFactory
|
15
24
|
include Carbon
|
16
|
-
attr_accessor :smokestack_size, :oven_count, :
|
25
|
+
attr_accessor :smokestack_size, :oven_count, :employees
|
26
|
+
class Mixer
|
27
|
+
attr_accessor :upc
|
28
|
+
def to_param
|
29
|
+
upc
|
30
|
+
end
|
31
|
+
end
|
32
|
+
def mixer
|
33
|
+
@mixer ||= Mixer.new
|
34
|
+
end
|
17
35
|
emit_as :factory do
|
18
36
|
provide :smokestack_size
|
19
37
|
provide :oven_count
|
20
|
-
provide :
|
21
|
-
provide :
|
22
|
-
provide :personnel, :as => :employees
|
38
|
+
provide :employees, :as => :personnel
|
39
|
+
provide :mixer, :key => :upc
|
23
40
|
end
|
24
41
|
end
|
25
42
|
|
@@ -60,19 +77,37 @@ describe Carbon do
|
|
60
77
|
c.emission.should == 134.599
|
61
78
|
c.emission.response.raw_request.object_id.should_not == first_raw_request.object_id
|
62
79
|
end
|
80
|
+
|
81
|
+
it "should recalculate if parameters change (though the options hash)" do
|
82
|
+
c = RentalCar.new
|
83
|
+
c.model = 'Acura'
|
84
|
+
c.model_year = 2003
|
85
|
+
c.fuel_economy = 32
|
86
|
+
c.emission.should == 134.599
|
87
|
+
first_raw_request = c.emission.response.raw_request
|
88
|
+
c.emission(:timeframe => Timeframe.new(:year => 2009)).should == 134.599
|
89
|
+
c.emission.response.raw_request.object_id.should_not == first_raw_request.object_id
|
90
|
+
end
|
63
91
|
end
|
64
92
|
|
65
93
|
describe 'synchronous (realtime) requests' do
|
66
|
-
it 'should
|
94
|
+
it 'should send simple params' do
|
95
|
+
d = DonutFactory.new
|
96
|
+
d.oven_count = 12_000
|
97
|
+
d.emission.request.body.should =~ /oven_count=12000/
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'send complex params' do
|
67
101
|
d = DonutFactory.new
|
68
|
-
d.
|
69
|
-
d.emission.request.body.should =~ /mixer\[
|
102
|
+
d.mixer.upc = 123
|
103
|
+
d.emission.request.body.should =~ /mixer\[upc\]=123/
|
70
104
|
end
|
71
105
|
|
72
106
|
it 'should not send attributes that are blank' do
|
73
107
|
d = DonutFactory.new
|
74
|
-
d.
|
108
|
+
d.mixer.upc = 123
|
75
109
|
d.emission.request.body.should_not =~ /oven_count/
|
110
|
+
d.emission.request.body.should_not =~ /timeframe/
|
76
111
|
end
|
77
112
|
|
78
113
|
it 'should send the key' do
|
metadata
CHANGED
@@ -5,18 +5,19 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 2
|
9
|
+
- 0
|
10
|
+
version: 0.2.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Derek Kastner
|
14
14
|
- Seamus Abshere
|
15
|
+
- Andy Rossmeissl
|
15
16
|
autorequire:
|
16
17
|
bindir: bin
|
17
18
|
cert_chain: []
|
18
19
|
|
19
|
-
date: 2010-07-
|
20
|
+
date: 2010-07-21 00:00:00 -05:00
|
20
21
|
default_executable:
|
21
22
|
dependencies:
|
22
23
|
- !ruby/object:Gem::Dependency
|
@@ -67,9 +68,25 @@ dependencies:
|
|
67
68
|
type: :runtime
|
68
69
|
version_requirements: *id003
|
69
70
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
71
|
+
name: blockenspiel
|
71
72
|
prerelease: false
|
72
73
|
requirement: &id004 !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
hash: 23
|
79
|
+
segments:
|
80
|
+
- 0
|
81
|
+
- 3
|
82
|
+
- 2
|
83
|
+
version: 0.3.2
|
84
|
+
type: :runtime
|
85
|
+
version_requirements: *id004
|
86
|
+
- !ruby/object:Gem::Dependency
|
87
|
+
name: fakeweb
|
88
|
+
prerelease: false
|
89
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
73
90
|
none: false
|
74
91
|
requirements:
|
75
92
|
- - ">="
|
@@ -81,11 +98,11 @@ dependencies:
|
|
81
98
|
- 8
|
82
99
|
version: 1.2.8
|
83
100
|
type: :development
|
84
|
-
version_requirements: *
|
101
|
+
version_requirements: *id005
|
85
102
|
- !ruby/object:Gem::Dependency
|
86
103
|
name: rspec
|
87
104
|
prerelease: false
|
88
|
-
requirement: &
|
105
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
89
106
|
none: false
|
90
107
|
requirements:
|
91
108
|
- - ">="
|
@@ -99,8 +116,8 @@ dependencies:
|
|
99
116
|
- 17
|
100
117
|
version: 2.0.0.beta.17
|
101
118
|
type: :development
|
102
|
-
version_requirements: *
|
103
|
-
description: Carbon
|
119
|
+
version_requirements: *id006
|
120
|
+
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.
|
104
121
|
email: derek.kastner@brighterplanet.com
|
105
122
|
executables: []
|
106
123
|
|
@@ -156,7 +173,7 @@ rubyforge_project:
|
|
156
173
|
rubygems_version: 1.3.7
|
157
174
|
signing_key:
|
158
175
|
specification_version: 3
|
159
|
-
summary:
|
176
|
+
summary: Carbon is a Ruby API wrapper for the Brighter Planet emission estimate web service (http://carbon.brighterplanet.com).
|
160
177
|
test_files:
|
161
178
|
- spec/lib/carbon_spec.rb
|
162
179
|
- spec/spec_helper.rb
|