carbon 1.1.3 → 2.0.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.
Files changed (39) hide show
  1. data/.gitignore +4 -22
  2. data/CHANGELOG +11 -0
  3. data/Gemfile +10 -1
  4. data/README.markdown +185 -0
  5. data/Rakefile +13 -26
  6. data/bin/carbon +3 -3
  7. data/carbon.gemspec +17 -23
  8. data/developer_notes/MULTI.markdown +25 -0
  9. data/developer_notes/REDUCE_HTTP_CONNECTIONS.markdown +46 -0
  10. data/features/shell.feature +1 -1
  11. data/features/support/env.rb +3 -4
  12. data/lib/carbon.rb +242 -96
  13. data/lib/carbon/registry.rb +50 -0
  14. data/lib/carbon/shell.rb +14 -8
  15. data/lib/carbon/shell/emitter.rb +33 -29
  16. data/lib/carbon/version.rb +1 -1
  17. data/test/carbon_test.rb +167 -0
  18. metadata +128 -182
  19. data/MIT-LICENSE.txt +0 -19
  20. data/README.rdoc +0 -266
  21. data/doc/INTEGRATION_GUIDE.rdoc +0 -1002
  22. data/doc/examining-response-with-jsonview.png +0 -0
  23. data/doc/shell_example +0 -43
  24. data/doc/timeout-error.png +0 -0
  25. data/doc/with-committee-reports.png +0 -0
  26. data/doc/without-committee-reports.png +0 -0
  27. data/lib/carbon/base.rb +0 -62
  28. data/lib/carbon/emission_estimate.rb +0 -165
  29. data/lib/carbon/emission_estimate/request.rb +0 -100
  30. data/lib/carbon/emission_estimate/response.rb +0 -61
  31. data/lib/carbon/emission_estimate/storage.rb +0 -33
  32. data/spec/fixtures/vcr_cassettes/flight.yml +0 -47
  33. data/spec/fixtures/vcr_cassettes/residence.yml +0 -44
  34. data/spec/lib/carbon/emission_estimate/request_spec.rb +0 -41
  35. data/spec/lib/carbon/emission_estimate/response_spec.rb +0 -33
  36. data/spec/lib/carbon/emission_estimate_spec.rb +0 -32
  37. data/spec/lib/carbon_spec.rb +0 -384
  38. data/spec/spec_helper.rb +0 -60
  39. data/spec/specwatchr +0 -60
@@ -1,47 +0,0 @@
1
- ---
2
- - !ruby/struct:VCR::HTTPInteraction
3
- request: !ruby/struct:VCR::Request
4
- method: :post
5
- uri: http://carbon.brighterplanet.com:80/flights.json
6
- body: !!null
7
- headers:
8
- content-type:
9
- - application/x-www-form-urlencoded
10
- response: !ruby/struct:VCR::Response
11
- status: !ruby/struct:VCR::ResponseStatus
12
- code: 200
13
- message: OK
14
- headers:
15
- server:
16
- - nginx/0.7.67
17
- date:
18
- - Thu, 17 Nov 2011 15:53:19 GMT
19
- content-type:
20
- - application/json
21
- transfer-encoding:
22
- - chunked
23
- connection:
24
- - keep-alive
25
- status:
26
- - 200 OK
27
- body: ! '{"emission":1092.2723218858448,"emitter":"Flight","timeframe":"2011-01-01/2012-01-01","emission_units":"kilograms","methodology":"http://impact.brighterplanet.com/flights","execution_id":"UNSUPPORTED","scope":"The
28
- flight greenhouse gas emission is the anthropogenic greenhouse gas emissions
29
- attributed to a single passenger on this flight. It includes CO2 emissions from
30
- combustion of non-biogenic fuel and extra forcing effects of high-altitude fuel
31
- combustion.","complies":[],"errors":[],"equivalents":{"cars_off_the_road_for_a_year":0.19879356258322375,"cars_off_the_road_for_a_month":2.3833382063549133,"cars_off_the_road_for_a_week":10.327434803430663,"cars_off_the_road_for_a_day":72.48974491427597,"cars_to_priuses_for_a_year":0.3975871251664475,"cars_to_priuses_for_a_month":4.766676412709827,"cars_to_priuses_for_a_week":20.654869606861325,"cars_to_priuses_for_a_day":144.97948982855195,"one_way_domestic_flight":3.5498850461289955,"round_trip_domestic_flight":1.7749425230644977,"one_way_cross_country_flight":1.2473749915936347,"round_trip_cross_country_flight":0.6236874957968174,"vegan_meals_instead_of_non_vegan_ones":878.9373378813549,"days_of_veganism":292.97911262711824,"weeks_of_veganism":41.8536908300218,"months_of_veganism":9.766006829981338,"years_of_veganism":0.802820156586096,"barrels_of_petroleum":2.540625420706475,"canisters_of_bbq_propane":45.5117108360175,"railroad_cars_full_of_coal":0.005461361609429225,"homes_energy_in_a_year":0.10595041522292695,"homes_energy_in_a_month":1.2659436210656942,"homes_energy_in_a_week":5.484299328188827,"homes_energy_in_a_day":38.49932252951037,"homes_electricity_in_a_year":0.1605640313172192,"homes_electricity_in_a_month":1.9213070141972008,"homes_electricity_in_a_week":8.32529963741391,"homes_electricity_in_a_day":58.43547694857081,"homes_with_lowered_thermostat_2_degrees_for_a_winter":5.7333374175788,"homes_with_raised_thermostat_3_degrees_for_a_summer":2.577762679650594,"replaced_refrigerators":1.0999182281390458,"loads_of_cold_laundry":500.8745804686168,"lightbulbs_for_a_year":2.0163347062012695,"lightbulbs_for_a_month":24.537897711165503,"lightbulbs_for_a_week":105.16179460652536,"lightbulbs_for_a_day":736.1358390626432,"lightbulbs_for_an_evening":4416.816126648181,"lightbulbs_to_CFLs_for_a_day":12529.975725977742,"lightbulbs_to_CFLs_for_a_week":1789.9962202047284,"lightbulbs_to_CFLs_for_a_month":417.666367259675,"lightbulbs_to_CFLs_for_a_year":34.32902680455022,"days_with_lightbulbs_to_CFLs":278.4442448397833,"weeks_with_lightbulbs_to_CFLs":39.777281146116806,"months_with_lightbulbs_to_CFLs":9.281037919064023,"years_with_lightbulbs_to_CFLs":0.7624060806763198,"recycled_kgs_of_trash":753.2910681501824,"recycled_bags_of_trash":417.3954837238473},"reports":[{"committee":{"name":"emission"},"conclusion":{"value":1092.2723218858448,"units":"kilograms"},"quorum":{"name":"from
32
- fuel use and greenhouse gas emission factor"}},{"committee":{"name":"ghg_emission_factor"},"conclusion":5.15214,"quorum":{"name":"from
33
- fuel and aviation multiplier"}},{"committee":{"name":"aviation_multiplier"},"conclusion":2.0,"quorum":{"name":"default"}},{"committee":{"name":"energy"},"conclusion":{"value":7976.996543941375,"units":"megajoules"},"quorum":{"name":"from
34
- fuel use and fuel"}},{"committee":{"name":"fuel_use"},"conclusion":212.00361828014084,"quorum":{"name":"from
35
- fuel per segment, segments per trip, trips, freight_share, passengers, seat
36
- class multiplier, fuel, date, and timeframe"}},{"committee":{"name":"fuel_per_segment"},"conclusion":8444.423485578423,"quorum":{"name":"from
37
- adjusted distance per segment and fuel use coefficients"}},{"committee":{"name":"seat_class_multiplier"},"conclusion":1.0,"quorum":{"name":"default"}},{"committee":{"name":"distance_class"},"conclusion":{"flight_distance_class":{"distance":1108.0,"distance_units":"kilometres","max_distance":3700.0,"max_distance_units":"kilometres","min_distance":0.0,"min_distance_units":"kilometres","name":"short
38
- haul"}},"quorum":{"name":"from adjusted distance per segment"}},{"committee":{"name":"adjusted_distance_per_segment"},"conclusion":952.9200693676661,"quorum":{"name":"from
39
- adjusted distance and segments per trip"}},{"committee":{"name":"adjusted_distance"},"conclusion":1600.905716537679,"quorum":{"name":"from
40
- distance, route inefficiency factor, and dogleg factor"}},{"committee":{"name":"distance"},"conclusion":1250.472807191592,"quorum":{"name":"default"}},{"committee":{"name":"route_inefficiency_factor"},"conclusion":1.100000023841858,"quorum":{"name":"default"}},{"committee":{"name":"dogleg_factor"},"conclusion":1.1638548181950328,"quorum":{"name":"from
41
- segments per trip"}},{"committee":{"name":"fuel_use_coefficients"},"conclusion":{"m3":1.0627617772702186e-07,"m2":-0.0001553124677028947,"m1":7.176288726885266,"b":1655.0651026365715},"quorum":{"name":"default"}},{"committee":{"name":"fuel"},"conclusion":{"fuel":{"biogenic_fraction":0.0,"carbon_content":18.672,"carbon_content_units":"grams_per_megajoule","co2_biogenic_emission_factor":0.0,"co2_biogenic_emission_factor_units":"kilograms_per_litre","co2_emission_factor":2.57607,"co2_emission_factor_units":"kilograms_per_litre","density":0.8156,"density_units":"kilograms_per_litre","energy_content":37.6267,"energy_content_units":"megajoules_per_litre","name":"Jet
42
- Fuel","oxidation_factor":1.0}},"quorum":{"name":"default"}},{"committee":{"name":"passengers"},"conclusion":130,"quorum":{"name":"from
43
- seats and load factor"}},{"committee":{"name":"seats"},"conclusion":168.87079036564523,"quorum":{"name":"default"}},{"committee":{"name":"load_factor"},"conclusion":0.7706950558978438,"quorum":{"name":"default"}},{"committee":{"name":"freight_share"},"conclusion":0.06795767512927696,"quorum":{"name":"default"}},{"committee":{"name":"trips"},"conclusion":1.7,"quorum":{"name":"default"}},{"committee":{"name":"segments_per_trip"},"conclusion":1.68,"quorum":{"name":"default"}},{"committee":{"name":"date"},"conclusion":"2011-01-01","quorum":{"name":"from
44
- timeframe"}}],"date":"2011-01-01","segments_per_trip":1.68,"trips":1.7,"freight_share":0.06795767512927696,"load_factor":0.7706950558978438,"seats":168.87079036564523,"passengers":130,"fuel":{"fuel":{"biogenic_fraction":0.0,"carbon_content":18.672,"carbon_content_units":"grams_per_megajoule","co2_biogenic_emission_factor":0.0,"co2_biogenic_emission_factor_units":"kilograms_per_litre","co2_emission_factor":2.57607,"co2_emission_factor_units":"kilograms_per_litre","density":0.8156,"density_units":"kilograms_per_litre","energy_content":37.6267,"energy_content_units":"megajoules_per_litre","name":"Jet
45
- Fuel","oxidation_factor":1.0}},"fuel_use_coefficients":{"m3":1.0627617772702186e-07,"m2":-0.0001553124677028947,"m1":7.176288726885266,"b":1655.0651026365715},"dogleg_factor":1.1638548181950328,"route_inefficiency_factor":1.100000023841858,"distance":1250.472807191592,"adjusted_distance":1600.905716537679,"adjusted_distance_per_segment":952.9200693676661,"distance_class":{"flight_distance_class":{"distance":1108.0,"distance_units":"kilometres","max_distance":3700.0,"max_distance_units":"kilometres","min_distance":0.0,"min_distance_units":"kilometres","name":"short
46
- haul"}},"seat_class_multiplier":1.0,"fuel_per_segment":8444.423485578423,"fuel_use":212.00361828014084,"energy":{"value":7976.996543941375,"units":"megajoules"},"aviation_multiplier":2.0,"ghg_emission_factor":5.15214,"carbon":{"value":1092.2723218858448,"units":"kilograms"}}'
47
- http_version: '1.1'
@@ -1,44 +0,0 @@
1
- ---
2
- - !ruby/struct:VCR::HTTPInteraction
3
- request: !ruby/struct:VCR::Request
4
- method: :post
5
- uri: http://carbon.brighterplanet.com:80/residences.json
6
- body: !!null
7
- headers:
8
- content-type:
9
- - application/x-www-form-urlencoded
10
- response: !ruby/struct:VCR::Response
11
- status: !ruby/struct:VCR::ResponseStatus
12
- code: 200
13
- message: OK
14
- headers:
15
- server:
16
- - nginx/0.7.67
17
- date:
18
- - Thu, 17 Nov 2011 16:06:52 GMT
19
- content-type:
20
- - application/json
21
- transfer-encoding:
22
- - chunked
23
- connection:
24
- - keep-alive
25
- status:
26
- - 200 OK
27
- body: ! '{"emission":3913.377091407546,"emitter":"Residence","timeframe":"2011-01-01/2012-01-01","emission_units":"kilograms","methodology":"http://impact.brighterplanet.com/residences","execution_id":"UNSUPPORTED","scope":null,"complies":[],"errors":[],"equivalents":{"cars_off_the_road_for_a_year":0.7122346306361733,"cars_off_the_road_for_a_month":8.538988813451265,"cars_off_the_road_for_a_week":37.000980399258346,"cars_off_the_road_for_a_day":259.71518404835314,"cars_to_priuses_for_a_year":1.4244692612723466,"cars_to_priuses_for_a_month":17.07797762690253,"cars_to_priuses_for_a_week":74.00196079851669,"cars_to_priuses_for_a_day":519.4303680967063,"one_way_domestic_flight":12.718475547074522,"round_trip_domestic_flight":6.359237773537261,"one_way_cross_country_flight":4.469076638387417,"round_trip_cross_country_flight":2.2345383191937085,"vegan_meals_instead_of_non_vegan_ones":3149.043671553464,"days_of_veganism":1049.6812238511545,"weeks_of_veganism":149.95278338855434,"months_of_veganism":34.98950457427486,"years_of_veganism":2.876332162184546,"barrels_of_petroleum":9.10251511461395,"canisters_of_bbq_propane":163.05868326767822,"railroad_cars_full_of_coal":0.01956688545703773,"homes_energy_in_a_year":0.3795975778665319,"homes_energy_in_a_month":4.535604048941346,"homes_energy_in_a_week":19.64906637595729,"homes_energy_in_a_day":137.93480234084177,"homes_electricity_in_a_year":0.5752664324369092,"homes_electricity_in_a_month":6.883630303785873,"homes_electricity_in_a_week":29.827760190708315,"homes_electricity_in_a_day":209.3617610132123,"homes_with_lowered_thermostat_2_degrees_for_a_winter":20.54131635279821,"homes_with_raised_thermostat_3_degrees_for_a_summer":9.23556993572181,"replaced_refrigerators":3.9407707310473987,"loads_of_cold_laundry":1794.526025790027,"lightbulbs_for_a_year":7.22409411073833,"lightbulbs_for_a_month":87.9140163584705,"lightbulbs_for_a_week":376.7721196065357,"lightbulbs_for_a_day":2637.416577377024,"lightbulbs_for_an_evening":15824.503377639234,"lightbulbs_to_CFLs_for_a_day":44892.21138303146,"lightbulbs_to_CFLs_for_a_week":6413.17193661104,"lightbulbs_to_CFLs_for_a_month":1496.4088723436914,"lightbulbs_to_CFLs_for_a_year":122.99352860584776,"days_with_lightbulbs_to_CFLs":997.6059148957943,"weeks_with_lightbulbs_to_CFLs":142.5134535377886,"months_with_lightbulbs_to_CFLs":33.251965145689915,"years_with_lightbulbs_to_CFLs":2.7315372098024673,"recycled_kgs_of_trash":2698.880077974671,"recycled_bags_of_trash":1495.4383548250225},"reports":[{"committee":{"name":"emission"},"conclusion":{"value":3913.377091407546,"units":"kilograms"},"quorum":{"name":"from
28
- fuel and electricity use and occupation and residents"}},{"committee":{"name":"fuel_oil_consumed"},"conclusion":199.07480656200002,"quorum":{"name":"from
29
- research"}},{"committee":{"name":"natural_gas_consumed"},"conclusion":42683876171.345726,"quorum":{"name":"from
30
- research"}},{"committee":{"name":"propane_consumed"},"conclusion":183.25178523799994,"quorum":{"name":"from
31
- research"}},{"committee":{"name":"biomass_consumed"},"conclusion":3798201078.0000005,"quorum":{"name":"from
32
- research"}},{"committee":{"name":"kerosene_consumed"},"conclusion":4.050390626,"quorum":{"name":"from
33
- research"}},{"committee":{"name":"coal_consumed"},"conclusion":2.871239704507795,"quorum":{"name":"from
34
- research"}},{"committee":{"name":"dirty_electricity_generated"},"conclusion":11462.092843034108,"quorum":{"name":"from
35
- electricity generated and green electricity"}},{"committee":{"name":"green_electricity"},"conclusion":0.0,"quorum":{"name":"default"}},{"committee":{"name":"electricity_generated"},"conclusion":11462.092843034108,"quorum":{"name":"from
36
- electricity used and loss rate"}},{"committee":{"name":"electricity_used"},"conclusion":10752.83,"quorum":{"name":"from
37
- research"}},{"committee":{"name":"missing_annual_energy"},"conclusion":0,"quorum":{"name":"from
38
- fuel reports"}},{"committee":{"name":"electricity_loss_rate"},"conclusion":0.061879,"quorum":{"name":"default"}},{"committee":{"name":"electricity_emission_factor"},"conclusion":0.6060757767293904,"quorum":{"name":"default"}},{"committee":{"name":"occupation"},"conclusion":0.937,"quorum":{"name":"default"}},{"committee":{"name":"residents"},"conclusion":2.57,"quorum":{"name":"default"}},{"committee":{"name":"air_conditioner_use"},"conclusion":{"air_conditioner_use":{"fugitive_emission":0.4994479354338,"fugitive_emission_units":"kilograms_per_square_metre"}},"quorum":{"name":"default"}},{"committee":{"name":"predicted_fuel_shares"},"conclusion":{"fuel_oil":0.41679323558325115,"natural_gas":0.1613371881024962,"propane":0.25265921858930535,"kerosene":0.008254483221570639,"biomass":0.014356500316711278,"coal":0.0002819952830220514,"electricity":0.14631737890364346},"quorum":{"name":"from
39
- research"}},{"committee":{"name":"predicted_annual_energy_consumption"},"conclusion":264563159141.1461,"quorum":{"name":"from
40
- research"}},{"committee":{"name":"predicted_annual_fuel_oil_consumption"},"conclusion":199.07480656200002,"quorum":{"name":"default"}},{"committee":{"name":"predicted_annual_natural_gas_consumption"},"conclusion":42683876171.345726,"quorum":{"name":"default"}},{"committee":{"name":"predicted_annual_propane_consumption"},"conclusion":183.25178523799997,"quorum":{"name":"default"}},{"committee":{"name":"predicted_annual_kerosene_consumption"},"conclusion":4.050390626,"quorum":{"name":"default"}},{"committee":{"name":"predicted_annual_biomass_consumption"},"conclusion":3798201078.0,"quorum":{"name":"default"}},{"committee":{"name":"predicted_annual_coal_consumption"},"conclusion":2.871239704507795,"quorum":{"name":"default"}},{"committee":{"name":"predicted_annual_electricity_use"},"conclusion":10752.83,"quorum":{"name":"default"}},{"committee":{"name":"active_subtimeframe"},"conclusion":{"startDate":"2011-01-01","endDate":"2012-01-01"},"quorum":{"name":"from
41
- acquisition and retirement"}},{"committee":{"name":"acquisition"},"conclusion":"2011-01-01","quorum":{"name":"from
42
- retirement"}},{"committee":{"name":"retirement"},"conclusion":"2012-01-01","quorum":{"name":"from
43
- acquisition"}},{"committee":{"name":"floorspace_estimate"},"conclusion":214.47688717440002,"quorum":{"name":"default"}}],"floorspace_estimate":214.47688717440002,"retirement":"2012-01-01","acquisition":"2011-01-01","active_subtimeframe":{"startDate":"2011-01-01","endDate":"2012-01-01"},"predicted_annual_electricity_use":10752.83,"predicted_annual_coal_consumption":2.871239704507795,"predicted_annual_biomass_consumption":3798201078.0,"predicted_annual_kerosene_consumption":4.050390626,"predicted_annual_propane_consumption":183.25178523799997,"predicted_annual_natural_gas_consumption":42683876171.345726,"predicted_annual_fuel_oil_consumption":199.07480656200002,"predicted_annual_energy_consumption":264563159141.1461,"predicted_fuel_shares":{"fuel_oil":0.41679323558325115,"natural_gas":0.1613371881024962,"propane":0.25265921858930535,"kerosene":0.008254483221570639,"biomass":0.014356500316711278,"coal":0.0002819952830220514,"electricity":0.14631737890364346},"air_conditioner_use":{"air_conditioner_use":{"fugitive_emission":0.4994479354338,"fugitive_emission_units":"kilograms_per_square_metre"}},"residents":2.57,"occupation":0.937,"electricity_emission_factor":0.6060757767293904,"electricity_loss_rate":0.061879,"missing_annual_energy":0,"electricity_used":10752.83,"electricity_generated":11462.092843034108,"green_electricity":0.0,"dirty_electricity_generated":11462.092843034108,"coal_consumed":2.871239704507795,"kerosene_consumed":4.050390626,"biomass_consumed":3798201078.0000005,"propane_consumed":183.25178523799994,"natural_gas_consumed":42683876171.345726,"fuel_oil_consumed":199.07480656200002,"carbon":{"value":3913.377091407546,"units":"kilograms"}}'
44
- http_version: '1.1'
@@ -1,41 +0,0 @@
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
- it 'includes compliance' do
23
- emission_estimate.comply = :iso
24
- request.params.should include(:comply => :iso)
25
- end
26
- end
27
-
28
- describe '#validate' do
29
- it 'warns the user if no key is given' do
30
- Carbon.should_receive :warn
31
- request.validate({})
32
- end
33
- it 'does nothing if all parameters are OK' do
34
- Carbon.should_not_receive :warn
35
- request.validate(
36
- :key => 'ABC123'
37
- )
38
- end
39
- end
40
- end
41
-
@@ -1,33 +0,0 @@
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 not rescue from generic network errors' do
25
- response.should_receive(:perform).once.ordered.
26
- and_raise EOFError
27
-
28
- lambda {
29
- response.send :load_realtime_data
30
- }.should raise_error EOFError
31
- end
32
- end
33
- end
@@ -1,32 +0,0 @@
1
- require 'spec_helper'
2
- require 'uri'
3
-
4
- describe Carbon::EmissionEstimate do
5
- describe '.parse' do
6
- it 'parses a standard CM1 response' do
7
- response = nil
8
- VCR.use_cassette('flight', :record => :once) do
9
- response = Net::HTTP.post_form(URI('http://carbon.brighterplanet.com/flights.json'), {})
10
- end
11
- estimate = Carbon::EmissionEstimate.parse response.body
12
- estimate['emission'].should > 0
13
- end
14
- it 'parses a CM1 response with an active_subtimeframe' do
15
- response = nil
16
- VCR.use_cassette('residence', :record => :once) do
17
- response = Net::HTTP.post_form(URI('http://carbon.brighterplanet.com/residences.json'), {})
18
- end
19
- estimate = Carbon::EmissionEstimate.parse response.body
20
- estimate['active_subtimeframe'].should be_a(Timeframe)
21
- end
22
- end
23
-
24
- describe '#take_options' do
25
- it 'accepts the :comply option' do
26
- estimate = Carbon::EmissionEstimate.new(RentalCar.new)
27
- estimate.take_options :comply => :iso
28
- estimate.comply.should == :iso
29
- end
30
- end
31
- end
32
-
@@ -1,384 +0,0 @@
1
- require 'spec_helper'
2
-
3
- CALLBACK_URL = 'http://www.postbin.org/1dj0146'
4
- KEY = 'valid'
5
- EXISTING_UNIQUE_ID = 'oisjoaioijodijaosijdoias'
6
- MISSING_UNIQUE_ID = 'd09joijdoijaloijdoais'
7
- OTHER_UNIQUE_ID = '1092fjoid;oijsao;ga'
8
-
9
- FakeWeb.register_uri :post,
10
- %r{http://carbon.brighterplanet.com/automobile_trips},
11
- :status => ["200", "OK"],
12
- :body => {
13
- 'emission' => '134.599',
14
- 'emission_units' => 'kilograms',
15
- 'methodology' => 'http://carbon.brighterplanet.com/something',
16
- 'active_subtimeframe' => Timeframe.new(:year => 2008)
17
- }.to_json
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
- #
29
- FakeWeb.register_uri :post,
30
- /carbon.brighterplanet.com.factories/,
31
- :status => ["200", "OK"],
32
- :body => {
33
- 'emission' => 1000.0,
34
- 'emission_units' => 'kilograms',
35
- 'methodology' => 'http://carbon.brighterplanet.com/something',
36
- 'active_subtimeframe' => Timeframe.new(:year => 2008)
37
- }.to_json
38
- #
39
- FakeWeb.register_uri :post,
40
- /queue.amazonaws.com/,
41
- :status => ["200", "OK"],
42
- :body => 'You would see an amazon aws response'
43
- # yep, it's stored!
44
- FakeWeb.register_uri :get,
45
- "http://storage.carbon.brighterplanet.com/#{Digest::SHA1.hexdigest(KEY+EXISTING_UNIQUE_ID)}",
46
- :status => ["200", "OK"],
47
- :body => {
48
- 'emission' => 1234,
49
- 'emission_units' => 'kilograms',
50
- 'methodology' => 'http://carbon.brighterplanet.com/something',
51
- 'updated_at' => Time.now.as_json
52
- }.to_json
53
- #
54
- FakeWeb.register_uri :get,
55
- "http://storage.carbon.brighterplanet.com/#{Digest::SHA1.hexdigest(KEY+OTHER_UNIQUE_ID)}",
56
- :status => ["200", "OK"],
57
- :body => {
58
- 'emission' => 99982,
59
- 'emission_units' => 'kilograms',
60
- 'methodology' => 'http://carbon.brighterplanet.com/something',
61
- 'updated_at' => Time.now.as_json
62
- }.to_json
63
- #
64
- FakeWeb.register_uri :get,
65
- "http://storage.carbon.brighterplanet.com/#{Digest::SHA1.hexdigest(KEY+MISSING_UNIQUE_ID)}",
66
- [
67
- {
68
- :status => ["404", "Not Found"],
69
- :body => "It's not here, you better ask carbon for it!"
70
- },
71
- {
72
- :status => ["200", "OK"],
73
- :body => {
74
- 'emission' => 9876,
75
- 'emission_units' => 'kilograms',
76
- 'methodology' => 'http://carbon.brighterplanet.com/something',
77
- 'updated_at' => Time.now.as_json
78
- }.to_json
79
- }
80
- ]
81
- #
82
- # FakeWeb.register_uri :post,
83
- # /carbon.brighterplanet.com.*#{MISSING_UNIQUE_ID}/,
84
- # :status => ["302", "Moved Permanently"],
85
- # :body => {
86
- # 'emission' => 9876,
87
- # 'emission_units' => 'kilograms',
88
- # 'methodology' => 'http://carbon.brighterplanet.com/something'
89
- # }.to_json,
90
- # :headers => { 'Location' => "http://storage.carbon.brighterplanet.com/#{Digest::SHA1.hexdigest(KEY+MISSING_UNIQUE_ID)}" }
91
-
92
-
93
- # set up timeouts
94
- module Carbon
95
- class EmissionEstimate
96
- attr_accessor :sleep_before_performing
97
- VALID_OPTIONS.push :sleep_before_performing
98
- class Response
99
- def perform_request_with_delay
100
- sleep parent.sleep_before_performing if parent.sleep_before_performing
101
- perform_request_without_delay
102
- end
103
- alias_method_chain :perform_request, :delay
104
- end
105
- end
106
- end
107
-
108
- describe Carbon do
109
- before(:each) do
110
- Carbon.key = KEY
111
- end
112
-
113
- it 'should be simple to use' do
114
- c = RentalCar.new
115
- c.model = 'Acura'
116
- c.model_year = 2003
117
- c.fuel_economy = 32
118
- c.emission_estimate.should == 134.599
119
- c.emission_estimate.emission_units.should == 'kilograms'
120
- end
121
-
122
- describe 'caching' do
123
- it "should keep around estimates if the parameters don't change" do
124
- c = RentalCar.new
125
- c.model = 'Acura'
126
- c.model_year = 2003
127
- c.fuel_economy = 32
128
- c.emission_estimate.should == 134.599
129
- first_raw_request = c.emission_estimate.response.raw_request
130
- c.emission_estimate.should == 134.599
131
- c.emission_estimate.response.raw_request.object_id.should == first_raw_request.object_id
132
- end
133
-
134
- it "should recalculate if parameters change" do
135
- c = RentalCar.new
136
- c.model = 'Acura'
137
- c.model_year = 2003
138
- c.fuel_economy = 32
139
- c.emission_estimate.should == 134.599
140
- first_raw_request = c.emission_estimate.response.raw_request
141
- c.model = 'Honda'
142
- c.emission_estimate.should == 134.599
143
- c.emission_estimate.response.raw_request.object_id.should_not == first_raw_request.object_id
144
- end
145
-
146
- it "should recalculate if parameters change (though the options hash)" do
147
- c = RentalCar.new
148
- c.model = 'Acura'
149
- c.model_year = 2003
150
- c.fuel_economy = 32
151
- c.emission_estimate.should == 134.599
152
- first_raw_request = c.emission_estimate.response.raw_request
153
- c.emission_estimate(:timeframe => Timeframe.new(:year => 2009)).should == 134.599
154
- c.emission_estimate.response.raw_request.object_id.should_not == first_raw_request.object_id
155
- end
156
-
157
- it "should recalculate if the callback changes" do
158
- c = RentalCar.new
159
- c.model = 'Acura'
160
- c.emission_estimate.should == 134.599
161
- first_raw_request = c.emission_estimate.response.raw_request
162
- c.emission_estimate.callback = CALLBACK_URL
163
- c.emission_estimate.response.raw_request.object_id.should_not == first_raw_request.object_id
164
- end
165
- end
166
-
167
- describe 'requests that can be stored (cached) by guid' do
168
- it 'should find existing unique ids on S3' do
169
- d = DonutFactory.new
170
- d.emission_estimate(:guid => EXISTING_UNIQUE_ID).should == 1234
171
- d.emission_estimate(:guid => EXISTING_UNIQUE_ID).updated_at.should be_instance_of(Time)
172
- end
173
- it "should pass through to realtime if unique id isn't found on S3" do
174
- d = DonutFactory.new
175
- d.emission_estimate(:guid => MISSING_UNIQUE_ID).should == 1000
176
- d.emission_estimate(:guid => MISSING_UNIQUE_ID).response.data.keys.should_not include('updated_at')
177
- d1 = DonutFactory.new
178
- d1.emission_estimate(:guid => MISSING_UNIQUE_ID).should == 9876
179
- d1.emission_estimate(:guid => MISSING_UNIQUE_ID).updated_at.should be_instance_of(Time)
180
- end
181
- it "should depend on the user to update the guid if they want a new estimate" do
182
- d = DonutFactory.new
183
- d.oven_count = 12_000
184
- str1 = d.emission_estimate(:guid => EXISTING_UNIQUE_ID).methodology
185
- str1.should equal(d.emission_estimate(:guid => EXISTING_UNIQUE_ID).methodology)
186
- d.oven_count = 13_000
187
- str1.should equal(d.emission_estimate(:guid => EXISTING_UNIQUE_ID).methodology)
188
- str1.should_not equal(d.emission_estimate(:guid => OTHER_UNIQUE_ID).methodology)
189
- end
190
- it 'should be deferrable for use in 2-pass reporting systems' do
191
- d = DonutFactory.new
192
- d.emission_estimate(:guid => EXISTING_UNIQUE_ID, :defer => true).number.should be_nil
193
- d.emission_estimate(:guid => EXISTING_UNIQUE_ID, :defer => true).request.url.should =~ /amazonaws/
194
- end
195
- it 'should complain if you provide defer but not guid' do
196
- d = DonutFactory.new
197
- lambda {
198
- d.emission_estimate(:defer => true).request.params
199
- }.should raise_error(ArgumentError, /defer.*guid/i)
200
- end
201
- it 'should complain if you provide guid and callback' do
202
- d = DonutFactory.new
203
- lambda {
204
- d.emission_estimate(:defer => true, :callback => 'foobar').request.params
205
- }.should raise_error(ArgumentError, /callback.*defer/i)
206
- end
207
- it 'should send guid along with other parameters when queueing up deferred request' do
208
- d = DonutFactory.new
209
- d.emission_estimate(:guid => EXISTING_UNIQUE_ID, :defer => true).request.params[:MessageBody].should =~ /#{EXISTING_UNIQUE_ID.to_query(:guid)}/
210
- end
211
- end
212
-
213
- describe 'synchronous (realtime) requests' do
214
- it 'should send simple params' do
215
- d = DonutFactory.new
216
- d.oven_count = 12_000
217
- d.emission_estimate.request.body.should =~ /oven_count=12000/
218
- end
219
-
220
- it 'send complex params' do
221
- d = DonutFactory.new
222
- d.mixer.upc = 123
223
- d.emission_estimate.request.body.should include({:mixer => { :upc => 123 }}.to_query)
224
- end
225
-
226
- it 'should not send attributes that are blank' do
227
- d = DonutFactory.new
228
- d.mixer.upc = 123
229
- d.emission_estimate.request.body.should_not =~ /oven_count/
230
- d.emission_estimate.request.body.should_not =~ /timeframe/
231
- end
232
-
233
- it 'should send attributes that are false' do
234
- d = DonutFactory.new
235
- d.mixer.upc = false
236
- d.emission_estimate.request.body.should include({:mixer => { :upc => 'false' }}.to_query)
237
- end
238
-
239
- it 'should send the key' do
240
- d = DonutFactory.new
241
- d.emission_estimate.request.body.should =~ /key=valid/
242
- end
243
-
244
- it 'should override defaults' do
245
- d = DonutFactory.new
246
- key = 'ADifferentOne'
247
- d.emission_estimate.key.should == KEY
248
- d.emission_estimate.key = key
249
- d.emission_estimate.key.should == key
250
- end
251
-
252
- it 'should accept timeouts' do
253
- d = DonutFactory.new
254
- lambda {
255
- d.emission_estimate(:sleep_before_performing => 2, :timeout => 1).to_f
256
- }.should raise_error(::Timeout::Error)
257
- end
258
-
259
- it 'should accept timeframes' do
260
- c = RentalCar.new
261
- t = Timeframe.new(:year => 2009)
262
- c.emission_estimate.timeframe = t
263
- c.emission_estimate.request.body.should include(t.to_query(:timeframe))
264
- end
265
-
266
- it 'should accept timeframes inline' do
267
- c = RentalCar.new
268
- t = Timeframe.new(:year => 2009)
269
- c.emission_estimate(:timeframe => t)
270
- c.emission_estimate.request.body.should include(t.to_query(:timeframe))
271
- end
272
-
273
- it 'should read active subtimeframes back from calculations' do
274
- c = RentalCar.new
275
- c.emission_estimate.active_subtimeframe.should == Timeframe.new(:year => 2008)
276
- end
277
-
278
- it 'should not generate post bodies with lots of empty params' do
279
- c = RentalCar.new
280
- c.emission_estimate :timeframe => Timeframe.new(:year => 2009)
281
- c.emission_estimate.request.body.should_not include('&&')
282
- c.emission_estimate.request.body.should_not =~ /=[^a-z0-9]/i
283
- end
284
-
285
- it 'should do certified calculations' do
286
- c = RentalCar.new
287
- c.emission_estimate.certified = true
288
- c.emission_estimate.should == 54321
289
- end
290
-
291
- it 'should do certified calculations (inline)' do
292
- c = RentalCar.new
293
- c.emission_estimate(:certified => true).should == 54321
294
- end
295
-
296
- it 'complies to given standards' do
297
- c = RentalCar.new
298
- c.emission_estimate(:comply => :iso).request.body.should =~ /comply=iso/
299
- end
300
- end
301
-
302
- describe 'asynchronous (queued) requests' do
303
- it 'should post a message to SQS' do
304
- c = RentalCar.new
305
- c.emission_estimate.callback = CALLBACK_URL
306
- c.emission_estimate.request.url.should =~ /queue.amazonaws.com/
307
- end
308
-
309
- it 'should default to non-certified' do
310
- c = RentalCar.new
311
- c.emission_estimate.callback = CALLBACK_URL
312
- c.emission_estimate.request.url.should_not =~ /certified/
313
- end
314
-
315
- it 'should accept certified' do
316
- c = RentalCar.new
317
- c.emission_estimate.callback = CALLBACK_URL
318
- c.emission_estimate.certified = true
319
- c.emission_estimate.request.url.should =~ /certified/
320
- end
321
-
322
- it 'should have nil data in its response' do
323
- c = RentalCar.new
324
- c.emission_estimate.callback = CALLBACK_URL
325
- c.emission_estimate.number.should be_nil
326
- c.emission_estimate.emission_units.should be_nil
327
- c.emission_estimate.methodology.should be_nil
328
- end
329
-
330
- it "should not compare itself to numbers" do
331
- c = RentalCar.new
332
- c.emission_estimate.callback = CALLBACK_URL
333
- c.emission_estimate.should_not == 0.0
334
- end
335
-
336
- it 'should not allow itself to be treated as a number' do
337
- c = RentalCar.new
338
- c.emission_estimate.callback = CALLBACK_URL
339
- lambda {
340
- c.emission_estimate + 5
341
- }.should raise_error(::Carbon::TriedToUseAsyncResponseAsNumber)
342
- lambda {
343
- c.emission_estimate.to_f
344
- }.should raise_error(::Carbon::TriedToUseAsyncResponseAsNumber)
345
- end
346
- end
347
-
348
- describe 'internally' do
349
- it "should ignore invalid options passed to #emission_estimate" do
350
- c = RentalCar.new
351
- t = Timeframe.new(:year => 2009)
352
- c.emission_estimate :timeframe => t, :method_missing => 'helo there', :response => 'foo'
353
- c.emission_estimate.instance_variable_get(:@timeframe).object_id.should == t.object_id
354
- c.emission_estimate.instance_variable_get(:@method_missing).should be_nil
355
- c.emission_estimate.instance_variable_get(:@response).should be_nil
356
- end
357
-
358
- it "should raise an error on EmissionEstimate if method isn't found" do
359
- c = RentalCar.new
360
- lambda {
361
- c.emission_estimate.foobar
362
- }.should raise_error(NoMethodError, /EmissionEstimate/)
363
- end
364
-
365
- it "should use #to_characteristic instead of #to_param if it's available" do
366
- d = DonutFactory.new
367
- lambda {
368
- d.mixer.to_param
369
- }.should raise_error(RuntimeError, /instead please/)
370
- lambda {
371
- d.emission_estimate.to_f
372
- }.should_not raise_error
373
- end
374
- end
375
- end
376
-
377
- # an average car emits 6 tons of carbon in a year
378
- # it 'should actually do a request!' do
379
- # FakeWeb.clean_registry
380
- # c = RentalCar.new
381
- # c.emission_estimate.to_i.should be_close(5500, 500)
382
- # c.emission_estimate.emission_units.should == 'kilograms'
383
- # end
384
-