carbon 0.1.6 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|