earth 0.5.2 → 0.5.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. data/Gemfile +1 -1
  2. data/LICENSE-PREAMBLE +1 -1
  3. data/Rakefile +3 -0
  4. data/earth.gemspec +1 -1
  5. data/lib/earth.rb +7 -7
  6. data/lib/earth/air/aircraft.rb +15 -0
  7. data/lib/earth/air/aircraft/data_miner.rb +65 -77
  8. data/lib/earth/air/aircraft_class.rb +1 -1
  9. data/lib/earth/air/aircraft_fuel_use_equation.rb +1 -1
  10. data/lib/earth/air/airline.rb +1 -1
  11. data/lib/earth/air/airport.rb +1 -1
  12. data/lib/earth/air/bts_aircraft.rb +1 -1
  13. data/lib/earth/air/flight_distance_class.rb +1 -1
  14. data/lib/earth/air/flight_seat_class.rb +1 -1
  15. data/lib/earth/air/flight_segment.rb +1 -1
  16. data/lib/earth/air/flight_segment/data_miner.rb +24 -46
  17. data/lib/earth/automobile/automobile_fuel.rb +1 -1
  18. data/lib/earth/automobile/automobile_make.rb +1 -1
  19. data/lib/earth/automobile/automobile_make_fleet_year.rb +1 -1
  20. data/lib/earth/automobile/automobile_make_model.rb +1 -1
  21. data/lib/earth/automobile/automobile_make_model_year.rb +1 -1
  22. data/lib/earth/automobile/automobile_make_model_year_variant.rb +1 -1
  23. data/lib/earth/automobile/automobile_make_year.rb +1 -1
  24. data/lib/earth/automobile/automobile_size_class.rb +1 -1
  25. data/lib/earth/automobile/automobile_size_class_year.rb +1 -1
  26. data/lib/earth/automobile/automobile_type_fuel_age.rb +1 -1
  27. data/lib/earth/automobile/automobile_type_fuel_control.rb +1 -1
  28. data/lib/earth/automobile/automobile_type_fuel_year.rb +1 -1
  29. data/lib/earth/automobile/automobile_type_fuel_year_age.rb +1 -1
  30. data/lib/earth/automobile/automobile_type_fuel_year_control.rb +1 -1
  31. data/lib/earth/automobile/automobile_type_year.rb +1 -1
  32. data/lib/earth/bus/bus_class.rb +1 -1
  33. data/lib/earth/bus/bus_fuel.rb +1 -1
  34. data/lib/earth/bus/bus_fuel_control.rb +1 -1
  35. data/lib/earth/bus/bus_fuel_year_control.rb +1 -1
  36. data/lib/earth/computation/computation_carrier.rb +1 -1
  37. data/lib/earth/computation/computation_carrier_instance_class.rb +1 -1
  38. data/lib/earth/computation/computation_carrier_region.rb +1 -1
  39. data/lib/earth/conversions_ext.rb +1 -0
  40. data/lib/earth/diet/diet_class.rb +1 -1
  41. data/lib/earth/diet/food_group.rb +1 -1
  42. data/lib/earth/fuel/fuel.rb +1 -1
  43. data/lib/earth/fuel/fuel_price.rb +1 -1
  44. data/lib/earth/fuel/fuel_type.rb +1 -1
  45. data/lib/earth/fuel/fuel_year.rb +1 -1
  46. data/lib/earth/fuel/greenhouse_gas.rb +1 -1
  47. data/lib/earth/hospitality/lodging_class.rb +1 -1
  48. data/lib/earth/industry/industry.rb +1 -1
  49. data/lib/earth/industry/industry_product.rb +1 -1
  50. data/lib/earth/industry/industry_product_line.rb +1 -1
  51. data/lib/earth/industry/industry_sector.rb +1 -1
  52. data/lib/earth/industry/merchant.rb +1 -1
  53. data/lib/earth/industry/merchant_category.rb +1 -1
  54. data/lib/earth/industry/merchant_category_industry.rb +1 -1
  55. data/lib/earth/industry/product_line.rb +1 -1
  56. data/lib/earth/industry/product_line_industry_product.rb +1 -1
  57. data/lib/earth/industry/sector.rb +1 -1
  58. data/lib/earth/locality/census_division.rb +1 -1
  59. data/lib/earth/locality/census_region.rb +1 -1
  60. data/lib/earth/locality/climate_division.rb +1 -1
  61. data/lib/earth/locality/country.rb +1 -1
  62. data/lib/earth/locality/egrid_region.rb +1 -1
  63. data/lib/earth/locality/egrid_region/data_miner.rb +10 -0
  64. data/lib/earth/locality/egrid_subregion.rb +1 -1
  65. data/lib/earth/locality/petroleum_administration_for_defense_district.rb +1 -1
  66. data/lib/earth/locality/state.rb +1 -1
  67. data/lib/earth/locality/urbanity.rb +1 -1
  68. data/lib/earth/locality/zip_code.rb +1 -1
  69. data/lib/earth/pet/breed.rb +1 -1
  70. data/lib/earth/pet/breed_gender.rb +1 -1
  71. data/lib/earth/pet/gender.rb +1 -1
  72. data/lib/earth/pet/species.rb +1 -1
  73. data/lib/earth/rail/rail_class.rb +1 -1
  74. data/lib/earth/residence/air_conditioner_use.rb +1 -1
  75. data/lib/earth/residence/clothes_machine_use.rb +1 -1
  76. data/lib/earth/residence/dishwasher_use.rb +1 -1
  77. data/lib/earth/residence/residence_appliance.rb +1 -1
  78. data/lib/earth/residence/residence_class.rb +1 -1
  79. data/lib/earth/residence/residence_fuel_price.rb +1 -1
  80. data/lib/earth/residence/residence_fuel_type.rb +1 -1
  81. data/lib/earth/residence/residential_energy_consumption_survey_response.rb +1 -1
  82. data/lib/earth/residence/residential_energy_consumption_survey_response/data_miner.rb +9 -9
  83. data/lib/earth/shipping/carrier.rb +1 -1
  84. data/lib/earth/shipping/carrier_mode.rb +1 -1
  85. data/lib/earth/shipping/shipment_mode.rb +1 -1
  86. data/lib/earth/version.rb +1 -1
  87. data/spec/earth/air/aircraft_spec.rb +1 -1
  88. metadata +42 -44
data/Gemfile CHANGED
@@ -1,5 +1,5 @@
1
1
  gem 'data_miner', :path => ENV['LOCAL_DATA_MINER'] if ENV['LOCAL_DATA_MINER']
2
- gem 'create_table', :path => ENV['LOCAL_CREATE_TABLE'] if ENV['LOCAL_CREATE_TABLE']
2
+ gem 'force_schema', :path => ENV['LOCAL_FORCE_SCHEMA'] if ENV['LOCAL_FORCE_SCHEMA']
3
3
 
4
4
  source :rubygems
5
5
 
@@ -9,7 +9,7 @@ IDENTITY OF THE SOFTWARE MODULE COVERED BY LICENSE:
9
9
 
10
10
  This license covers the Brighter Planet reference data import module,
11
11
  referred to as 'earth,' officially distributed from
12
- http://github.com/brighterplanet/earth.
12
+ https://github.com/brighterplanet/earth.
13
13
 
14
14
  SCOPE OF THE SOFTWARE MODULE COVERED BY LICENSE:
15
15
 
data/Rakefile CHANGED
@@ -24,6 +24,9 @@ Cucumber::Rake::Task.new(:features) do |t|
24
24
  end
25
25
  end
26
26
 
27
+ directory 'log/'
28
+ task :features => 'log/'
29
+
27
30
  if RUBY_VERSION =~ /^1\.8/
28
31
  desc "Run cucumber tests with RCov"
29
32
  Cucumber::Rake::Task.new(:features_with_coverage) do |t|
@@ -36,7 +36,7 @@ Gem::Specification.new do |s|
36
36
  s.add_runtime_dependency 'geokit-rails'
37
37
  s.add_runtime_dependency 'loose_tight_dictionary', '>=0.2.3'
38
38
  s.add_runtime_dependency 'weighted_average'
39
- s.add_runtime_dependency 'create_table', '>=0.0.2'
39
+ s.add_runtime_dependency 'force_schema', '>=0.0.2'
40
40
  s.add_development_dependency 'bundler'
41
41
  s.add_development_dependency 'bueller'
42
42
  s.add_development_dependency 'cucumber'
@@ -7,7 +7,7 @@ require 'falls_back_on'
7
7
  require 'weighted_average'
8
8
  require 'fixed_width'
9
9
  require 'errata'
10
- require 'create_table'
10
+ require 'force_schema'
11
11
  require 'loose_tight_dictionary'
12
12
  require 'loose_tight_dictionary/cached_result'
13
13
 
@@ -119,13 +119,13 @@ module Earth
119
119
  resource_model.data_miner_config.steps.push pull_dependencies_step
120
120
  end
121
121
 
122
- def _prepend_create_table_step_to_data_miner(resource)
122
+ def _prepend_force_schema_step_to_data_miner(resource)
123
123
  resource_model = resource.constantize
124
- return if resource_model.data_miner_config.steps.any? { |step| step.description == :create_table! }
124
+ return if resource_model.data_miner_config.steps.any? { |step| step.description == :force_schema! }
125
125
 
126
- create_table_step = DataMiner::Process.new resource_model.data_miner_config, :create_table!
126
+ force_schema_step = DataMiner::Process.new resource_model.data_miner_config, :force_schema!
127
127
 
128
- resource_model.data_miner_config.steps.unshift create_table_step
128
+ resource_model.data_miner_config.steps.unshift force_schema_step
129
129
  end
130
130
 
131
131
  TAPS_STEP = 'Tap the Brighter Planet data server'
@@ -144,7 +144,7 @@ module Earth
144
144
  next unless ::Object.const_defined?(resource)
145
145
  _append_pull_dependencies_step_to_data_miner resource
146
146
  if options[:apply_schemas] or options[:load_data_miner]
147
- _prepend_create_table_step_to_data_miner resource
147
+ _prepend_force_schema_step_to_data_miner resource
148
148
  else
149
149
  _prepend_taps_step_to_data_miner resource
150
150
  end
@@ -154,7 +154,7 @@ module Earth
154
154
  def _load_schemas(selected_resources, options)
155
155
  return unless options[:apply_schemas]
156
156
  selected_resources.each do |resource|
157
- resource.constantize.create_table!
157
+ resource.constantize.force_schema!
158
158
  end
159
159
  end
160
160
  end
@@ -17,6 +17,21 @@ class Aircraft < ActiveRecord::Base
17
17
  end
18
18
  end
19
19
 
20
+ force_schema do
21
+ string 'icao_code'
22
+ string 'manufacturer_name'
23
+ string 'model_name'
24
+ string 'description'
25
+ string 'aircraft_type'
26
+ string 'engine_type'
27
+ integer 'engines'
28
+ string 'weight_class'
29
+ string 'class_code'
30
+ string 'fuel_use_code'
31
+ float 'seats'
32
+ float 'passengers'
33
+ end
34
+
20
35
  # Enable aircraft.flight_segments
21
36
  cache_loose_tight_dictionary_matches_with :flight_segments, :primary_key => :description, :foreign_key => :aircraft_description
22
37
  end
@@ -20,22 +20,69 @@ Aircraft.class_eval do
20
20
  @manufacturer_whitelist ||= RemoteTable.new(:url => 'https://spreadsheets.google.com/spreadsheet/pub?key=0AoQJbWqPrREqdFRFalpOdlg1cnF6amlSM1dDc1lya2c&output=csv').map { |record| record['Manufacturer'].to_regexp }
21
21
  @manufacturer_whitelist.any? { |manufacturer_regexp| manufacturer_regexp.match candidate }
22
22
  end
23
-
24
- create_table do
25
- string 'icao_code'
26
- string 'manufacturer_name'
27
- string 'model_name'
28
- string 'description'
29
- string 'aircraft_type'
30
- string 'engine_type'
31
- integer 'engines'
32
- string 'weight_class'
33
- string 'class_code'
34
- string 'fuel_use_code'
35
- float 'seats'
36
- float 'passengers'
23
+
24
+ # FIXME TODO do we want to restrict this to certain years?
25
+ # Derive some average characteristics from flight segments
26
+ def self.update_averages!
27
+ FlightSegment.run_data_miner!
28
+ manually_cache_flight_segments!
29
+ find_each do |aircraft|
30
+ aircraft.seats = aircraft.flight_segments.weighted_average :seats_per_flight, :weighted_by => :passengers
31
+ aircraft.passengers = aircraft.flight_segments.sum :passengers
32
+ aircraft.save
33
+ end
37
34
  end
38
35
 
36
+ # Cache fuzzy matches between FlightSegment aircraft_description and Aircraft description
37
+ def self.manually_cache_flight_segments!
38
+ FlightSegment.run_data_miner!
39
+ LooseTightDictionary::CachedResult.setup
40
+ FlightSegment.find_by_sql("SELECT * FROM flight_segments GROUP BY aircraft_description HAVING aircraft_description IS NOT NULL").each do |flight_segment|
41
+ original_description = flight_segment.aircraft_description
42
+
43
+ # If the flight segment's aircraft_description contains '/' then it describes multiple aircraft.
44
+ # We need to synthesize descriptions for those aircraft, find all Aircraft that fuzzily match the
45
+ # synthesized descriptions, and associate those Aircraft with the original aircraft_description.
46
+ # e.g. boeing 747-100/200
47
+ if original_description.include?("/")
48
+ # Pull out the complete first aircraft description
49
+ # e.g. 'boeing 747-100'
50
+ first_description = original_description.split('/')[0]
51
+
52
+ # Pull out the root of the description - the text up to and including the last ' ' or '-'
53
+ # e.g. 'boeing 747-'
54
+ root_length = first_description.rindex(/[ \-]/)
55
+ root = first_description.slice(0..root_length)
56
+
57
+ # Pull out the suffixes - the text separated by forward slashes
58
+ # e.g. ['100', '200']
59
+ suffixes = original_description.split(root)[1].split('/')
60
+
61
+ # Create an array of synthesized descriptions by appending each suffix to the root
62
+ # e.g. ['boeing 747-100', 'boeing 747-200']
63
+ suffixes.map{ |suffix| root + suffix }.each do |synthesized_description|
64
+ # Look up the Aircraft that match each synthesized description and associate
65
+ # them with the original flight segment aircraft_description
66
+ Aircraft.loose_tight_dictionary.find_all(synthesized_description).each do |aircraft|
67
+ attrs = {
68
+ :a_class => "Aircraft",
69
+ :a => aircraft.description,
70
+ :b_class => "FlightSegment",
71
+ :b => original_description
72
+ }
73
+ unless ::LooseTightDictionary::CachedResult.exists? attrs
74
+ ::LooseTightDictionary::CachedResult.create! attrs
75
+ end
76
+ end
77
+ end
78
+ # If the flight segment's aircraft_description doesn't contain '/' we can use
79
+ # a method provided by loose_tight_dictionary to associate it with Aircraft
80
+ else
81
+ flight_segment.cache_aircraft!
82
+ end
83
+ end
84
+ end
85
+
39
86
  data_miner do
40
87
  ('A'..'Z').each do |letter|
41
88
  import("aircraft made by whitelisted manufacturers whose ICAO code starts with '#{letter}' from the FAA",
@@ -73,13 +120,13 @@ Aircraft.class_eval do
73
120
  end
74
121
 
75
122
  process "Synthesize description from manufacturer name and model name" do
76
- Aircraft.find_each do |aircraft|
123
+ find_each do |aircraft|
77
124
  aircraft.update_attribute :description, [aircraft.manufacturer_name, aircraft.model_name].join(' ').downcase
78
125
  end
79
126
  end
80
127
 
81
128
  process "Synthesize class code from engine type and weight class" do
82
- Aircraft.find_each do |aircraft|
129
+ find_each do |aircraft|
83
130
  size = case aircraft.weight_class
84
131
  when 'Small', 'Small+', 'Light'
85
132
  'Light'
@@ -92,67 +139,8 @@ Aircraft.class_eval do
92
139
  end
93
140
  end
94
141
 
95
- process "Ensure FlightSegment is populated" do
96
- FlightSegment.run_data_miner!
97
- end
98
-
99
- process "Cache fuzzy matches between FlightSegment aircraft_description and Aircraft description" do
100
- LooseTightDictionary::CachedResult.setup
101
- FlightSegment.find_by_sql("SELECT * FROM flight_segments GROUP BY aircraft_description HAVING aircraft_description IS NOT NULL").each do |flight_segment|
102
- original_description = flight_segment.aircraft_description
103
-
104
- # If the flight segment's aircraft_description contains '/' then it describes multiple aircraft.
105
- # We need to synthesize descriptions for those aircraft, find all Aircraft that fuzzily match the
106
- # synthesized descriptions, and associate those Aircraft with the original aircraft_description.
107
- # e.g. boeing 747-100/200
108
- if original_description.include?("/")
109
- # Pull out the complete first aircraft description
110
- # e.g. 'boeing 747-100'
111
- first_description = original_description.split('/')[0]
112
-
113
- # Pull out the root of the description - the text up to and including the last ' ' or '-'
114
- # e.g. 'boeing 747-'
115
- root_length = first_description.rindex(/[ \-]/)
116
- root = first_description.slice(0..root_length)
117
-
118
- # Pull out the suffixes - the text separated by forward slashes
119
- # e.g. ['100', '200']
120
- suffixes = original_description.split(root)[1].split('/')
121
-
122
- # Create an array of synthesized descriptions by appending each suffix to the root
123
- # e.g. ['boeing 747-100', 'boeing 747-200']
124
- suffixes.map{ |suffix| root + suffix }.each do |synthesized_description|
125
- # Look up the Aircraft that match each synthesized description and associate
126
- # them with the original flight segment aircraft_description
127
- Aircraft.loose_tight_dictionary.find_all(synthesized_description).each do |aircraft|
128
- attrs = {
129
- :a_class => "Aircraft",
130
- :a => aircraft.description,
131
- :b_class => "FlightSegment",
132
- :b => original_description
133
- }
134
- unless ::LooseTightDictionary::CachedResult.exists? attrs
135
- ::LooseTightDictionary::CachedResult.create! attrs
136
- end
137
- end
138
- end
139
- # If the flight segment's aircraft_description doesn't contain '/' we can use
140
- # a method provided by loose_tight_dictionary to associate it with Aircraft
141
- else
142
- flight_segment.cache_aircraft!
143
- end
144
- end
145
- end
146
-
147
- # FIXME TODO do we want to restrict this to certain years?
148
- process "Derive some average characteristics from flight segments" do
149
- Aircraft.find_each do |aircraft|
150
- aircraft.seats = aircraft.flight_segments.weighted_average :seats_per_flight, :weighted_by => :passengers
151
- aircraft.passengers = aircraft.flight_segments.sum :passengers
152
- aircraft.save
153
- end
154
- end
155
-
142
+ process :update_averages!
143
+
156
144
  # FIXME TODO verify this
157
145
  end
158
146
  end
@@ -11,7 +11,7 @@ class AircraftClass < ActiveRecord::Base
11
11
  fuel_use_coefficients.all?(&:present?) and fuel_use_coefficients.any?(&:nonzero?)
12
12
  end
13
13
 
14
- create_table do
14
+ force_schema do
15
15
  string 'code'
16
16
  float 'm3'
17
17
  string 'm3_units'
@@ -20,7 +20,7 @@ class AircraftFuelUseEquation < ActiveRecord::Base
20
20
  fuel_use_coefficients.all?(&:present?) and fuel_use_coefficients.any?(&:nonzero?)
21
21
  end
22
22
 
23
- create_table do
23
+ force_schema do
24
24
  string 'code'
25
25
  string 'aircraft_description'
26
26
  float 'm3'
@@ -1,7 +1,7 @@
1
1
  class Airline < ActiveRecord::Base
2
2
  set_primary_key :name
3
3
 
4
- create_table do
4
+ force_schema do
5
5
  string 'name'
6
6
  string 'bts_code'
7
7
  string 'iata_code'
@@ -7,7 +7,7 @@ class Airport < ActiveRecord::Base
7
7
  :lat_column_name => :latitude,
8
8
  :lng_column_name => :longitude
9
9
 
10
- create_table do
10
+ force_schema do
11
11
  string 'iata_code'
12
12
  string 'name'
13
13
  string 'city'
@@ -1,6 +1,6 @@
1
1
  class BtsAircraft < ActiveRecord::Base
2
2
  set_primary_key :bts_code
3
- create_table do
3
+ force_schema do
4
4
  string 'bts_code'
5
5
  string 'description'
6
6
  end
@@ -1,6 +1,6 @@
1
1
  class FlightDistanceClass < ActiveRecord::Base
2
2
  set_primary_key :name
3
- create_table do
3
+ force_schema do
4
4
  string 'name'
5
5
  float 'distance'
6
6
  string 'distance_units'
@@ -3,7 +3,7 @@ class FlightSeatClass < ActiveRecord::Base
3
3
 
4
4
  falls_back_on :multiplier => 1
5
5
 
6
- create_table do
6
+ force_schema do
7
7
  string 'name'
8
8
  string 'distance_class_name'
9
9
  string 'seat_class_name'
@@ -19,7 +19,7 @@ class FlightSegment < ActiveRecord::Base
19
19
  :load_factor => lambda { weighted_average(:load_factor, :weighted_by => :passengers) }, # 0.78073233770097 data1 10-12-2010
20
20
  :freight_share => lambda { weighted_average(:freight_share, :weighted_by => :passengers) } # 0.022567224170157 data1 10-12-2010
21
21
 
22
- create_table do
22
+ force_schema do
23
23
  string 'row_hash' # auto-generated primary key
24
24
  string 'origin_airport_iata_code' # iata code
25
25
  string 'origin_airport_city' # city
@@ -10,6 +10,24 @@ FlightSegment.class_eval do
10
10
  end
11
11
  end
12
12
 
13
+ def self.update_averages!
14
+ # Derive load factor, which is passengers divided by available seats
15
+ update_all 'load_factor = passengers / seats', 'seats > 0'
16
+
17
+ # Assume a load factor of 1 where passengers > available seats
18
+ update_all 'load_factor = 1', 'passengers > seats AND seats > 0'
19
+
20
+ # TODO: what is 90.718474
21
+ # Derive freight share as a fraction of the total weight carried
22
+ update_all 'freight_share = (freight + mail) / (freight + mail + (passengers * 90.718474))', '(freight + mail + passengers) > 0'
23
+
24
+ # Derive average seats per flight
25
+ update_all 'seats_per_flight = seats / flights', 'flights > 0'
26
+
27
+ # Add a useful date field
28
+ update_all 'approximate_date = DATE(CONCAT_WS("-", year, month, "14"))', 'month IS NOT NULL'
29
+ end
30
+
13
31
  URL = 'http://www.transtats.bts.gov/DownLoad_Table.asp?Table_ID=293&Has_Group=3&Is_Zipped=0'
14
32
  FORM_DATA = %{
15
33
  UserTableName=T_100_Segment__All_Carriers&
@@ -201,10 +219,10 @@ FlightSegment.class_eval do
201
219
  store 'flights', :field_name => 'DEPARTURES_PERFORMED'
202
220
  store 'passengers', :field_name => 'PASSENGERS'
203
221
  store 'seats', :field_name => 'SEATS'
204
- store 'payload_capacity', :field_name => 'PAYLOAD', :units => 'pounds'
205
- store 'freight', :field_name => 'FREIGHT', :units => 'pounds'
206
- store 'mail', :field_name => 'MAIL', :units => 'pounds'
207
- store 'distance', :field_name => 'DISTANCE', :units => 'miles'
222
+ store 'payload_capacity', :field_name => 'PAYLOAD', :from_units => :pounds, :to_units => :kilograms
223
+ store 'freight', :field_name => 'FREIGHT', :from_units => :pounds, :to_units => :kilograms
224
+ store 'mail', :field_name => 'MAIL', :from_units => :pounds, :to_units => :kilograms
225
+ store 'distance', :field_name => 'DISTANCE', :from_units => :miles, :to_units => :kilometres
208
226
  store 'month', :field_name => 'MONTH'
209
227
  store 'year', :field_name => 'YEAR'
210
228
  store 'source', :static => 'BTS T100'
@@ -232,49 +250,9 @@ FlightSegment.class_eval do
232
250
  end
233
251
  end
234
252
 
235
- %w{ payload_capacity freight mail }.each do |field|
236
- process "Convert #{field} from pounds to kilograms" do
237
- conversion_factor = 1.pounds.to(:kilograms)
238
- connection.execute %{
239
- UPDATE flight_segments
240
- SET #{field} = #{field} * #{conversion_factor},
241
- #{field + '_units'} = 'kilograms'
242
- WHERE #{field + '_units'} = 'pounds'
243
- }
244
- end
245
- end
246
-
247
- process "Convert distance from miles to kilometres" do
248
- conversion_factor = 1.miles.to(:kilometres)
249
- connection.execute %{
250
- UPDATE flight_segments
251
- SET distance = distance * #{conversion_factor},
252
- distance_units = 'kilometres'
253
- WHERE distance_units = 'miles'
254
- }
255
- end
256
-
257
- process "Derive load factor, which is passengers divided by available seats" do
258
- update_all 'load_factor = passengers / seats', 'seats > 0'
259
- end
260
-
261
- process "Assume a load factor of 1 where passengers > available seats" do
262
- update_all 'load_factor = 1', 'passengers > seats AND seats > 0'
263
- end
264
-
265
- process "Derive freight share as a fraction of the total weight carried" do
266
- update_all 'freight_share = (freight + mail) / (freight + mail + (passengers * 90.718474))', '(freight + mail + passengers) > 0'
267
- end
268
-
269
- process "Derive average seats per flight" do
270
- update_all 'seats_per_flight = seats / flights', 'flights > 0'
271
- end
272
-
273
- process "Add a useful date field" do
274
- update_all 'approximate_date = DATE(CONCAT_WS("-", year, month, "14"))', 'month IS NOT NULL'
275
- end
253
+ process :update_averages!
276
254
 
277
- process "Data mine Aircraft to cache fuzzy matches" do
255
+ process "Data mine Aircraft because it's like a belongs-to association" do
278
256
  Aircraft.run_data_miner!
279
257
  end
280
258
 
@@ -98,7 +98,7 @@ class AutomobileFuel < ActiveRecord::Base
98
98
  :hfc_emission_factor => lambda { AutomobileFuel.fallback_hfc_emission_factor },
99
99
  :hfc_emission_factor_units => lambda { AutomobileFuel.fallback_hfc_emission_factor_units }
100
100
 
101
- create_table do
101
+ force_schema do
102
102
  string 'name'
103
103
  string 'code'
104
104
  string 'base_fuel_name'