emitter 0.5.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -1,3 +1,12 @@
1
+ gem 'sniff', :path => ENV['LOCAL_SNIFF'] if ENV['LOCAL_SNIFF']
2
+ gem 'data_miner', :path => ENV['LOCAL_DATA_MINER'] if ENV['LOCAL_DATA_MINER']
3
+ gem 'earth', :path => ENV['LOCAL_EARTH'] if ENV['LOCAL_EARTH']
4
+ gem 'create_table', :path => ENV['LOCAL_CREATE_TABLE'] if ENV['LOCAL_CREATE_TABLE']
5
+
1
6
  source :rubygems
2
7
 
3
- gemspec
8
+ gemspec :path => '.'
9
+
10
+ if RUBY_VERSION < "1.9"
11
+ gem 'fastercsv'
12
+ end
data/emitter.gemspec CHANGED
@@ -4,7 +4,7 @@ require "emitter/version"
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = 'emitter'
7
- s.version = Emitter::VERSION
7
+ s.version = Emitter::VERSION
8
8
  s.platform = Gem::Platform::RUBY
9
9
  s.authors = ["Andy Rossmeissl", "Seamus Abshere", "Ian Hough", "Matt Kling", 'Derek Kastner']
10
10
  s.email = %q{derek@brighterplanet.com}
@@ -17,17 +17,18 @@ Gem::Specification.new do |s|
17
17
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
18
  s.require_paths = ["lib"]
19
19
 
20
- s.add_dependency 'activesupport', '>=2.3.4'
21
- s.add_dependency 'charisma', '>=0.3.0'
20
+ s.add_dependency 'activesupport', '>=2.3.10'
21
+ s.add_dependency 'charisma'
22
22
  s.add_dependency 'cohort_scope'
23
- s.add_dependency 'data_miner', '>=1.1' unless ENV['LOCAL_DATA_MINER']
24
- s.add_dependency 'earth' unless ENV['LOCAL_EARTH']
25
- s.add_dependency 'falls_back_on' unless ENV['LOCAL_FALLS_BACK_ON']
26
- s.add_dependency 'leap' unless ENV['LOCAL_LEAP']
23
+ s.add_dependency 'data_miner', '>=1.2.1' unless ENV['LOCAL_DATA_MINER']
24
+ s.add_dependency 'earth', '>=0.5.1' unless ENV['LOCAL_EARTH']
25
+ s.add_dependency 'falls_back_on'
26
+ s.add_dependency 'leap'
27
27
  s.add_dependency 'summary_judgement'
28
28
  s.add_dependency 'timeframe'
29
29
  s.add_dependency 'weighted_average'
30
+ s.add_dependency 'create_table' unless ENV['LOCAL_CREATE_TABLE']
30
31
  s.add_development_dependency 'activerecord', '~>3'
31
32
  s.add_development_dependency 'bueller'
32
- s.add_development_dependency 'sniff'
33
+ s.add_development_dependency 'sniff', '>=0.8.2' unless ENV['LOCAL_SNIFF']
33
34
  end
data/lib/emitter.rb CHANGED
@@ -1,9 +1,14 @@
1
+ require 'active_support'
2
+ require 'active_support/core_ext'
1
3
  require 'leap'
2
4
  require 'cohort_scope'
3
5
  require 'charisma'
4
6
  require 'data_miner'
5
7
  require 'summary_judgement'
6
8
  require 'falls_back_on'
9
+ require 'create_table'
10
+
11
+ require 'emitter/measurement'
7
12
 
8
13
  module BrighterPlanet
9
14
  module Emitter
@@ -15,10 +20,17 @@ module BrighterPlanet
15
20
  summarization
16
21
  }
17
22
 
23
+ # "included" not "self.included"
24
+ # why?
25
+ # This module **extends other modules**
26
+ # it forcibly (over)writes their definitions of self.included
27
+ # BrighterPlanet::AutomobileTrip.extend(Emitter) -> now BrighterPlanet::AutomobileTrip has self.included
28
+ # MyAutomobileTrip.include(BrighterPlanet::AutomobileTrip) -> will call BrighterPlanet::AutomobileTrip.included(MyAutomobileTrip)
18
29
  def included(base)
19
30
  base.extend ClassMethods
20
-
21
- common_name = self.to_s.split('::').last.underscore
31
+
32
+ # here self is the emitter module
33
+ common_name = self.name.demodulize.underscore
22
34
  common_camel = common_name.camelcase
23
35
 
24
36
  REQUIRED_COMPONENTS.each do |component|
@@ -32,9 +44,24 @@ module BrighterPlanet
32
44
 
33
45
  base.send :include, ::Charisma
34
46
  base.send :include, "::BrighterPlanet::#{common_camel}::Characterization".constantize
35
- base._add_implicit_characteristics
47
+ base.class_eval do
48
+ preexisting = characterization.keys
49
+ decisions[:emission].committees.reject do |committee|
50
+ committee.name == :emission or preexisting.include?(committee.name)
51
+ end.each do |committee|
52
+ characterize do
53
+ has committee.name, :options => committee.options.slice(:measures, :display_with)
54
+ end
55
+ end
56
+ end
36
57
 
37
58
  base.send :include, "::BrighterPlanet::#{common_camel}::Data".constantize
59
+ unless base.data_miner_config.steps.any? { |step| step.description == :create_table! }
60
+ base.data_miner_config.steps.unshift ::DataMiner::Process.new(base.data_miner_config, :create_table!)
61
+ end
62
+ unless base.data_miner_config.steps.any? { |step| step.description == :run_data_miner_on_parent_associations! }
63
+ base.data_miner_config.steps.push ::DataMiner::Process.new(base.data_miner_config, :run_data_miner_on_parent_associations!)
64
+ end
38
65
 
39
66
  base.extend ::SummaryJudgement
40
67
  base.send :include, "::BrighterPlanet::#{common_camel}::Summarization".constantize
@@ -48,24 +75,17 @@ module BrighterPlanet
48
75
 
49
76
  base.send :include, "::BrighterPlanet::#{common_camel}::Relationships".constantize
50
77
  end
51
-
78
+
79
+ # this gets added as a class method to the emitter module
52
80
  def scope(statement)
53
81
  @emission_scope = statement
54
82
  end
55
83
 
56
84
  module ClassMethods
57
- def _add_implicit_characteristics
58
- preexisting = characterization.keys
59
- decisions[:emission].committees.reject do |committee|
60
- committee.name == :emission or preexisting.include?(committee.name)
61
- end.each do |committee|
62
- characterize do
63
- has committee.name, :options => committee.options.slice(:measures, :display_with)
64
- end
65
- end
85
+ # this will have been set by self.included on the emitter module
86
+ def emission_scope
87
+ @emission_scope
66
88
  end
67
-
68
- def emission_scope; @emission_scope end
69
89
  end
70
90
  end
71
91
  end
@@ -0,0 +1,46 @@
1
+ # encoding: UTF-8
2
+
3
+ # defined by charisma:
4
+ # length kilometres (see below)
5
+ # mass kilograms
6
+ # speed metres_per_second (see below)
7
+ # time seconds
8
+
9
+ module BrighterPlanet
10
+ module Measurement
11
+ class Area < ::Charisma::Measurement
12
+ units :square_metres => 'm²'
13
+ end
14
+
15
+ class Biomass < ::Charisma::Measurement
16
+ units :joules => 'J'
17
+ end
18
+
19
+ class Cost < ::Charisma::Measurement
20
+ units :dollars => 'USD'
21
+ end
22
+
23
+ class ElectricalEnergy < ::Charisma::Measurement
24
+ units :kilowatt_hours => 'kWh'
25
+ end
26
+
27
+ class Volume < ::Charisma::Measurement
28
+ units :litres => 'l'
29
+ end
30
+
31
+ # TODO use charisma default
32
+ class BigLength < ::Charisma::Measurement
33
+ units :kilometres => 'km'
34
+ end
35
+
36
+ # TODO units :metres_per_litre => 'm/l'
37
+ class BigLengthPerVolume < ::Charisma::Measurement
38
+ units :kilometres_per_litre => 'km/l'
39
+ end
40
+
41
+ # TODO use charisma default
42
+ class BigSpeed < ::Charisma::Measurement
43
+ units :kilometres_per_hour => 'km/h'
44
+ end
45
+ end
46
+ end
@@ -1,3 +1,3 @@
1
1
  module Emitter
2
- VERSION = '0.5.0'
2
+ VERSION = "0.5.1"
3
3
  end
data/spec/emitter_spec.rb CHANGED
@@ -10,7 +10,7 @@ describe BrighterPlanet::Emitter do
10
10
  $:.unshift File.expand_path('fixtures/dirigible/lib', File.dirname(__FILE__))
11
11
  require 'dirigible'
12
12
  Airship.send :include, BrighterPlanet::Dirigible
13
- Airship.execute_schema
13
+ Airship.create_table!
14
14
 
15
15
  $:.unshift File.expand_path('fixtures/biplane/lib', File.dirname(__FILE__))
16
16
  end
@@ -35,6 +35,19 @@ describe BrighterPlanet::Emitter do
35
35
  it 'should state its own scope' do
36
36
  Airship.emission_scope.should == 'Anthropogenic emissions resulting from the inflation, launching, and acceleration of dirigibles'
37
37
  end
38
+
39
+ it 'should have extra data_miner steps' do
40
+ Airship.data_miner_config.steps[0].description.should == :create_table!
41
+ Airship.data_miner_config.steps[1].description.should == "the first step defined in the emitter module"
42
+ Airship.data_miner_config.steps[2].description.should == :run_data_miner_on_parent_associations!
43
+ end
44
+
45
+ it 'should have units' do
46
+ a = Airship.new :distance => 1500, :surface_area => 200, :payload => 1000
47
+ a.characteristics[:distance].units.to_s[0..2].should == 'met' # meters or metres
48
+ a.characteristics[:payload].units.should == :kilograms
49
+ a.characteristics[:surface_area].units.should == :square_metres
50
+ end
38
51
  end
39
52
  end
40
53
 
@@ -3,8 +3,8 @@ module BrighterPlanet
3
3
  module Characterization
4
4
  def self.included(base)
5
5
  base.characterize do
6
- has :distance
7
- has :payload
6
+ has :distance, :measures => :length
7
+ has :payload, :measures => :mass
8
8
  has :dirigible_class
9
9
  end
10
10
  end
@@ -2,14 +2,10 @@ module BrighterPlanet
2
2
  module Biplane
3
3
  module Data
4
4
  def self.included(base)
5
- base.data_miner do
6
- schema do
7
- float :distance
8
- float :payload
9
- integer :dirigible_class_id
10
- end
11
-
12
- process :run_data_miner_on_belongs_to_associations
5
+ base.create_table do
6
+ float :distance
7
+ float :payload
8
+ integer :dirigible_class_id
13
9
  end
14
10
  end
15
11
  end
@@ -3,8 +3,9 @@ module BrighterPlanet
3
3
  module Characterization
4
4
  def self.included(base)
5
5
  base.characterize do
6
- has :distance
7
- has :payload
6
+ has :distance, :measures => :length
7
+ has :payload, :measures => :mass
8
+ has :surface_area, :measures => Measurement::Area
8
9
  has :dirigible_class
9
10
  end
10
11
  end
@@ -2,14 +2,17 @@ module BrighterPlanet
2
2
  module Dirigible
3
3
  module Data
4
4
  def self.included(base)
5
+ base.create_table do
6
+ float :distance
7
+ float :payload
8
+ float :surface_area
9
+ integer :dirigible_class_id
10
+ end
11
+
5
12
  base.data_miner do
6
- schema do
7
- float :distance
8
- float :payload
9
- integer :dirigible_class_id
13
+ process "the first step defined in the emitter module" do
14
+ # just make sure i'm here
10
15
  end
11
-
12
- process :run_data_miner_on_belongs_to_associations
13
16
  end
14
17
  end
15
18
  end
data/spec/spec_helper.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  require 'rubygems'
2
2
  require 'bundler'
3
3
  Bundler.setup
4
-
5
4
  require 'sniff'
6
5
  Sniff.init File.join(File.dirname(__FILE__), '..', '..')
7
6
 
metadata CHANGED
@@ -1,10 +1,10 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: emitter
3
- version: !ruby/object:Gem::Version
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.1
4
5
  prerelease:
5
- version: 0.5.0
6
6
  platform: ruby
7
- authors:
7
+ authors:
8
8
  - Andy Rossmeissl
9
9
  - Seamus Abshere
10
10
  - Ian Hough
@@ -13,162 +13,168 @@ authors:
13
13
  autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
-
17
- date: 2011-06-02 00:00:00 -05:00
18
- default_executable:
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
16
+ date: 2011-07-13 00:00:00.000000000Z
17
+ dependencies:
18
+ - !ruby/object:Gem::Dependency
21
19
  name: activesupport
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
20
+ requirement: &2159605280 !ruby/object:Gem::Requirement
24
21
  none: false
25
- requirements:
26
- - - ">="
27
- - !ruby/object:Gem::Version
28
- version: 2.3.4
22
+ requirements:
23
+ - - ! '>='
24
+ - !ruby/object:Gem::Version
25
+ version: 2.3.10
29
26
  type: :runtime
30
- version_requirements: *id001
31
- - !ruby/object:Gem::Dependency
32
- name: charisma
33
27
  prerelease: false
34
- requirement: &id002 !ruby/object:Gem::Requirement
28
+ version_requirements: *2159605280
29
+ - !ruby/object:Gem::Dependency
30
+ name: charisma
31
+ requirement: &2159604860 !ruby/object:Gem::Requirement
35
32
  none: false
36
- requirements:
37
- - - ">="
38
- - !ruby/object:Gem::Version
39
- version: 0.3.0
33
+ requirements:
34
+ - - ! '>='
35
+ - !ruby/object:Gem::Version
36
+ version: '0'
40
37
  type: :runtime
41
- version_requirements: *id002
42
- - !ruby/object:Gem::Dependency
43
- name: cohort_scope
44
38
  prerelease: false
45
- requirement: &id003 !ruby/object:Gem::Requirement
39
+ version_requirements: *2159604860
40
+ - !ruby/object:Gem::Dependency
41
+ name: cohort_scope
42
+ requirement: &2159604400 !ruby/object:Gem::Requirement
46
43
  none: false
47
- requirements:
48
- - - ">="
49
- - !ruby/object:Gem::Version
50
- version: "0"
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
51
48
  type: :runtime
52
- version_requirements: *id003
53
- - !ruby/object:Gem::Dependency
54
- name: data_miner
55
49
  prerelease: false
56
- requirement: &id004 !ruby/object:Gem::Requirement
50
+ version_requirements: *2159604400
51
+ - !ruby/object:Gem::Dependency
52
+ name: data_miner
53
+ requirement: &2159603880 !ruby/object:Gem::Requirement
57
54
  none: false
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: "1.1"
55
+ requirements:
56
+ - - ! '>='
57
+ - !ruby/object:Gem::Version
58
+ version: 1.2.1
62
59
  type: :runtime
63
- version_requirements: *id004
64
- - !ruby/object:Gem::Dependency
65
- name: earth
66
60
  prerelease: false
67
- requirement: &id005 !ruby/object:Gem::Requirement
61
+ version_requirements: *2159603880
62
+ - !ruby/object:Gem::Dependency
63
+ name: earth
64
+ requirement: &2159603320 !ruby/object:Gem::Requirement
68
65
  none: false
69
- requirements:
70
- - - ">="
71
- - !ruby/object:Gem::Version
72
- version: "0"
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: 0.5.1
73
70
  type: :runtime
74
- version_requirements: *id005
75
- - !ruby/object:Gem::Dependency
76
- name: falls_back_on
77
71
  prerelease: false
78
- requirement: &id006 !ruby/object:Gem::Requirement
72
+ version_requirements: *2159603320
73
+ - !ruby/object:Gem::Dependency
74
+ name: falls_back_on
75
+ requirement: &2159602900 !ruby/object:Gem::Requirement
79
76
  none: false
80
- requirements:
81
- - - ">="
82
- - !ruby/object:Gem::Version
83
- version: "0"
77
+ requirements:
78
+ - - ! '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
84
81
  type: :runtime
85
- version_requirements: *id006
86
- - !ruby/object:Gem::Dependency
87
- name: leap
88
82
  prerelease: false
89
- requirement: &id007 !ruby/object:Gem::Requirement
83
+ version_requirements: *2159602900
84
+ - !ruby/object:Gem::Dependency
85
+ name: leap
86
+ requirement: &2159602440 !ruby/object:Gem::Requirement
90
87
  none: false
91
- requirements:
92
- - - ">="
93
- - !ruby/object:Gem::Version
94
- version: "0"
88
+ requirements:
89
+ - - ! '>='
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
95
92
  type: :runtime
96
- version_requirements: *id007
97
- - !ruby/object:Gem::Dependency
98
- name: summary_judgement
99
93
  prerelease: false
100
- requirement: &id008 !ruby/object:Gem::Requirement
94
+ version_requirements: *2159602440
95
+ - !ruby/object:Gem::Dependency
96
+ name: summary_judgement
97
+ requirement: &2159601980 !ruby/object:Gem::Requirement
101
98
  none: false
102
- requirements:
103
- - - ">="
104
- - !ruby/object:Gem::Version
105
- version: "0"
99
+ requirements:
100
+ - - ! '>='
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
106
103
  type: :runtime
107
- version_requirements: *id008
108
- - !ruby/object:Gem::Dependency
109
- name: timeframe
110
104
  prerelease: false
111
- requirement: &id009 !ruby/object:Gem::Requirement
105
+ version_requirements: *2159601980
106
+ - !ruby/object:Gem::Dependency
107
+ name: timeframe
108
+ requirement: &2159601560 !ruby/object:Gem::Requirement
112
109
  none: false
113
- requirements:
114
- - - ">="
115
- - !ruby/object:Gem::Version
116
- version: "0"
110
+ requirements:
111
+ - - ! '>='
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
117
114
  type: :runtime
118
- version_requirements: *id009
119
- - !ruby/object:Gem::Dependency
115
+ prerelease: false
116
+ version_requirements: *2159601560
117
+ - !ruby/object:Gem::Dependency
120
118
  name: weighted_average
119
+ requirement: &2159601140 !ruby/object:Gem::Requirement
120
+ none: false
121
+ requirements:
122
+ - - ! '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ type: :runtime
121
126
  prerelease: false
122
- requirement: &id010 !ruby/object:Gem::Requirement
127
+ version_requirements: *2159601140
128
+ - !ruby/object:Gem::Dependency
129
+ name: create_table
130
+ requirement: &2159600400 !ruby/object:Gem::Requirement
123
131
  none: false
124
- requirements:
125
- - - ">="
126
- - !ruby/object:Gem::Version
127
- version: "0"
132
+ requirements:
133
+ - - ! '>='
134
+ - !ruby/object:Gem::Version
135
+ version: '0'
128
136
  type: :runtime
129
- version_requirements: *id010
130
- - !ruby/object:Gem::Dependency
131
- name: activerecord
132
137
  prerelease: false
133
- requirement: &id011 !ruby/object:Gem::Requirement
138
+ version_requirements: *2159600400
139
+ - !ruby/object:Gem::Dependency
140
+ name: activerecord
141
+ requirement: &2159599900 !ruby/object:Gem::Requirement
134
142
  none: false
135
- requirements:
143
+ requirements:
136
144
  - - ~>
137
- - !ruby/object:Gem::Version
138
- version: "3"
145
+ - !ruby/object:Gem::Version
146
+ version: '3'
139
147
  type: :development
140
- version_requirements: *id011
141
- - !ruby/object:Gem::Dependency
142
- name: bueller
143
148
  prerelease: false
144
- requirement: &id012 !ruby/object:Gem::Requirement
149
+ version_requirements: *2159599900
150
+ - !ruby/object:Gem::Dependency
151
+ name: bueller
152
+ requirement: &2159599480 !ruby/object:Gem::Requirement
145
153
  none: false
146
- requirements:
147
- - - ">="
148
- - !ruby/object:Gem::Version
149
- version: "0"
154
+ requirements:
155
+ - - ! '>='
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
150
158
  type: :development
151
- version_requirements: *id012
152
- - !ruby/object:Gem::Dependency
153
- name: sniff
154
159
  prerelease: false
155
- requirement: &id013 !ruby/object:Gem::Requirement
160
+ version_requirements: *2159599480
161
+ - !ruby/object:Gem::Dependency
162
+ name: sniff
163
+ requirement: &2159598900 !ruby/object:Gem::Requirement
156
164
  none: false
157
- requirements:
158
- - - ">="
159
- - !ruby/object:Gem::Version
160
- version: "0"
165
+ requirements:
166
+ - - ! '>='
167
+ - !ruby/object:Gem::Version
168
+ version: 0.8.2
161
169
  type: :development
162
- version_requirements: *id013
170
+ prerelease: false
171
+ version_requirements: *2159598900
163
172
  description: A software model in Ruby for the greenhouse gas emissions
164
173
  email: derek@brighterplanet.com
165
174
  executables: []
166
-
167
175
  extensions: []
168
-
169
176
  extra_rdoc_files: []
170
-
171
- files:
177
+ files:
172
178
  - .gitignore
173
179
  - Gemfile
174
180
  - LICENSE
@@ -177,6 +183,7 @@ files:
177
183
  - Rakefile
178
184
  - emitter.gemspec
179
185
  - lib/emitter.rb
186
+ - lib/emitter/measurement.rb
180
187
  - lib/emitter/version.rb
181
188
  - spec/emitter_spec.rb
182
189
  - spec/fixtures/biplane/lib/biplane.rb
@@ -193,35 +200,37 @@ files:
193
200
  - spec/fixtures/dirigible/lib/dirigible/relationships.rb
194
201
  - spec/fixtures/dirigible/lib/dirigible/summarization.rb
195
202
  - spec/spec_helper.rb
196
- has_rdoc: true
197
203
  homepage: https://github.com/brighterplanet/emitter
198
204
  licenses: []
199
-
200
205
  post_install_message:
201
206
  rdoc_options: []
202
-
203
- require_paths:
207
+ require_paths:
204
208
  - lib
205
- required_ruby_version: !ruby/object:Gem::Requirement
209
+ required_ruby_version: !ruby/object:Gem::Requirement
206
210
  none: false
207
- requirements:
208
- - - ">="
209
- - !ruby/object:Gem::Version
210
- version: "0"
211
- required_rubygems_version: !ruby/object:Gem::Requirement
211
+ requirements:
212
+ - - ! '>='
213
+ - !ruby/object:Gem::Version
214
+ version: '0'
215
+ segments:
216
+ - 0
217
+ hash: -3262676913904917466
218
+ required_rubygems_version: !ruby/object:Gem::Requirement
212
219
  none: false
213
- requirements:
214
- - - ">="
215
- - !ruby/object:Gem::Version
216
- version: "0"
220
+ requirements:
221
+ - - ! '>='
222
+ - !ruby/object:Gem::Version
223
+ version: '0'
224
+ segments:
225
+ - 0
226
+ hash: -3262676913904917466
217
227
  requirements: []
218
-
219
228
  rubyforge_project:
220
- rubygems_version: 1.6.2
229
+ rubygems_version: 1.8.5
221
230
  signing_key:
222
231
  specification_version: 3
223
232
  summary: The mother of all carbon models
224
- test_files:
233
+ test_files:
225
234
  - spec/emitter_spec.rb
226
235
  - spec/fixtures/biplane/lib/biplane.rb
227
236
  - spec/fixtures/biplane/lib/biplane/carbon_model.rb