data_miner 1.1.8 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -11,12 +11,7 @@ You define <tt>data_miner</tt> blocks in your ActiveRecord models. For example,
11
11
  class Country < ActiveRecord::Base
12
12
  set_primary_key :iso_3166_code
13
13
 
14
- data_miner do
15
- schema do
16
- string 'iso_3166_code'
17
- string 'name'
18
- end
19
-
14
+ data_miner do
20
15
  import 'the official ISO country list',
21
16
  :url => 'http://www.iso.org/iso/list-en1-semic-3.txt',
22
17
  :skip => 2,
@@ -34,6 +29,36 @@ Now you can run:
34
29
  irb(main):001:0> Country.run_data_miner!
35
30
  => nil
36
31
 
32
+ == Creating tables from scratch (changed in 1.2)
33
+
34
+ We recommend using the <tt>create_table</tt> gem (https://github.com/seamusabshere/create_table)
35
+
36
+ This replaces the <tt>schema</tt> method that was available before. It didn't make sense for <tt>data_miner</tt> to provide this natively.
37
+
38
+ class Car < ActiveRecord::Base
39
+
40
+ # THE NEW WAY - depends on create_table gem, which is not required by default
41
+ # see the process step in the data_miner block where we actually call create_table!
42
+ create_table do
43
+ string :make
44
+ string :model
45
+ end
46
+
47
+ data_miner do
48
+ # DEPRECATED - see above
49
+ # schema do
50
+ # string :make
51
+ # string :model
52
+ # end
53
+
54
+ process "create the table, adding and removing columns as necessary" do
55
+ create_table!
56
+ end
57
+
58
+ # [... other data mining steps]
59
+ end
60
+ end
61
+
37
62
  ==Advanced usage
38
63
 
39
64
  This is how we linked together (http://data.brighterplanet.com/aircraft) the FAA's list of aircraft with the US Department of Transportations list of aircraft:
@@ -44,6 +69,36 @@ This is how we linked together (http://data.brighterplanet.com/aircraft) the FAA
44
69
  # table without breaking associations.
45
70
  set_primary_key :icao_code
46
71
 
72
+ # Use the create_table gem to define the database schema in-line.
73
+ # It will destructively and automatically add/remove columns.
74
+ # This is "OK" because you can always just re-run the import script to get the data back.
75
+ # PS. If you're using DataMapper, you don't need this
76
+ create_table do
77
+ string 'icao_code'
78
+ string 'manufacturer_name'
79
+ string 'name'
80
+ string 'bts_name'
81
+ string 'bts_aircraft_type_code'
82
+ string 'brighter_planet_aircraft_class_code'
83
+ string 'fuel_use_aircraft_name'
84
+ float 'm3'
85
+ string 'm3_units'
86
+ float 'm2'
87
+ string 'm2_units'
88
+ float 'm1'
89
+ string 'm1_units'
90
+ float 'endpoint_fuel'
91
+ string 'endpoint_fuel_units'
92
+ float 'seats'
93
+ float 'distance'
94
+ string 'distance_units'
95
+ float 'load_factor'
96
+ float 'freight_share'
97
+ float 'payload'
98
+ float 'weighting'
99
+ index 'bts_aircraft_type_code'
100
+ end
101
+
47
102
  # A dictionary between BTS aircraft type codes and ICAO aircraft
48
103
  # codes that uses string similarity instead of exact matching.
49
104
  # This is preferable to typing everything out.
@@ -154,36 +209,6 @@ This is how we linked together (http://data.brighterplanet.com/aircraft) the FAA
154
209
  raise DataMiner::Skip unless DataMiner::Run.allowed? Aircraft
155
210
  end
156
211
 
157
- # Define the database schema in-line.
158
- # It will destructively and automatically add/remove columns.
159
- # This is "OK" because you can always just re-run the import script to get the data back.
160
- # PS. if we were using DataMapper, we wouldn't need this.
161
- schema :options => 'ENGINE=InnoDB default charset=utf8' do
162
- string 'icao_code'
163
- string 'manufacturer_name'
164
- string 'name'
165
- string 'bts_name'
166
- string 'bts_aircraft_type_code'
167
- string 'brighter_planet_aircraft_class_code'
168
- string 'fuel_use_aircraft_name'
169
- float 'm3'
170
- string 'm3_units'
171
- float 'm2'
172
- string 'm2_units'
173
- float 'm1'
174
- string 'm1_units'
175
- float 'endpoint_fuel'
176
- string 'endpoint_fuel_units'
177
- float 'seats'
178
- float 'distance'
179
- string 'distance_units'
180
- float 'load_factor'
181
- float 'freight_share'
182
- float 'payload'
183
- float 'weighting'
184
- index 'bts_aircraft_type_code'
185
- end
186
-
187
212
  # The FAA publishes a document to help people identify aircraft by different names.
188
213
  ('A'..'Z').each do |letter|
189
214
  import( "ICAO aircraft codes starting with the letter #{letter} used by the FAA",
data/data_miner.gemspec CHANGED
@@ -27,13 +27,14 @@ Gem::Specification.new do |s|
27
27
  s.add_dependency 'blockenspiel', '>=0.3.2'
28
28
  s.add_dependency 'taps', '>=0.3.11'
29
29
  s.add_dependency 'errata', '>=1.0.1'
30
+ s.add_development_dependency 'create_table', '>=0.0.2'
30
31
  s.add_development_dependency 'loose_tight_dictionary', ">=0.0.5"
31
32
  s.add_development_dependency 'test-unit'
32
33
  s.add_development_dependency 'shoulda'
33
34
  s.add_development_dependency 'mysql'
34
- if RUBY_VERSION >= '1.9'
35
- s.add_development_dependency 'ruby-debug19'
36
- else
37
- s.add_development_dependency 'ruby-debug'
38
- end
35
+ # if RUBY_VERSION >= '1.9'
36
+ # s.add_development_dependency 'ruby-debug19'
37
+ # else
38
+ # s.add_development_dependency 'ruby-debug'
39
+ # end
39
40
  end
@@ -6,8 +6,6 @@ class DataMiner
6
6
  def data_miner(options = {}, &blk)
7
7
  ::DataMiner.instance.start_logging
8
8
 
9
- ::DataMiner.logger.debug "Database table `#{table_name}` doesn't exist. It might be created in the data_miner block, but if it's not, DataMiner probably won't work properly until you run a migration or otherwise fix the schema." unless table_exists?
10
-
11
9
  ::DataMiner.instance.resource_names.push self.name unless ::DataMiner.instance.resource_names.include? self.name
12
10
 
13
11
  # this is class_eval'ed here so that each ActiveRecord descendant has its own copy, or none at all
@@ -19,11 +17,6 @@ class DataMiner
19
17
  def self.run_data_miner!(options = {})
20
18
  data_miner_config.run options
21
19
  end
22
- def self.execute_schema
23
- if schema = data_miner_config.steps.detect { |s| s.instance_of?(::DataMiner::Schema) }
24
- schema.run
25
- end
26
- end
27
20
  end
28
21
 
29
22
  if options[:append]
@@ -18,13 +18,7 @@ class DataMiner
18
18
  # def attributes
19
19
  # @attributes ||= {}
20
20
  # end
21
-
22
- def schema(create_table_options = {}, &blk)
23
- step = Schema.new self, create_table_options
24
- ::Blockenspiel.invoke blk, step
25
- steps.push step
26
- end
27
-
21
+
28
22
  def process(method_id_or_block_description, &blk)
29
23
  step = Process.new self, method_id_or_block_description, &blk
30
24
  steps.push step
@@ -5,6 +5,8 @@ class DataMiner
5
5
  attr_reader :block_description
6
6
  attr_reader :blk
7
7
 
8
+ alias :description :block_description
9
+
8
10
  def initialize(config, method_id_or_block_description, &blk)
9
11
  @config = config
10
12
  if block_given?
@@ -1,3 +1,3 @@
1
1
  class DataMiner
2
- VERSION = '1.1.8'
2
+ VERSION = '1.2.0'
3
3
  end
data/lib/data_miner.rb CHANGED
@@ -26,7 +26,6 @@ class DataMiner
26
26
  autoload :Tap, 'data_miner/tap'
27
27
  autoload :Process, 'data_miner/process'
28
28
  autoload :Run, 'data_miner/run'
29
- autoload :Schema, 'data_miner/schema'
30
29
  autoload :Verify, 'data_miner/verify'
31
30
 
32
31
  class << self
data/test/helper.rb CHANGED
@@ -3,7 +3,8 @@ require 'bundler'
3
3
  Bundler.setup
4
4
  require 'test/unit'
5
5
  require 'shoulda'
6
- require 'ruby-debug'
6
+ require 'create_table'
7
+ # require 'ruby-debug'
7
8
  $LOAD_PATH.unshift(File.dirname(__FILE__))
8
9
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
9
10
  require 'data_miner'
@@ -42,8 +42,8 @@ class AutomobileVariant < ActiveRecord::Base
42
42
  }
43
43
 
44
44
  class ParserB
45
- require 'slither'
46
- ::Slither.define :fuel_economy_guide_b do |d|
45
+ require 'fixed_width'
46
+ ::FixedWidth.define :fuel_economy_guide_b do |d|
47
47
  d.rows do |row|
48
48
  row.trap { true } # there's only one section
49
49
  row.column 'active_year' , 4, :type => :integer # ACTIVE YEAR
@@ -567,18 +567,22 @@ end
567
567
  class AutomobileMakeFleetYear < ActiveRecord::Base
568
568
  set_primary_key :name
569
569
 
570
+ create_table do
571
+ string "name"
572
+ string "make_name"
573
+ string "fleet"
574
+ integer "year"
575
+ float "fuel_efficiency"
576
+ string "fuel_efficiency_units"
577
+ integer "volume"
578
+ string "make_year_name"
579
+ datetime "created_at"
580
+ datetime "updated_at"
581
+ end
582
+
570
583
  data_miner do
571
- schema :id => false do
572
- string "name"
573
- string "make_name"
574
- string "fleet"
575
- integer "year"
576
- float "fuel_efficiency"
577
- string "fuel_efficiency_units"
578
- integer "volume"
579
- string "make_year_name"
580
- datetime "created_at"
581
- datetime "updated_at"
584
+ process "create table" do
585
+ create_table!
582
586
  end
583
587
 
584
588
  process "finish if i tell you to" do
@@ -605,298 +609,307 @@ end
605
609
 
606
610
  class CensusDivisionTrois < ActiveRecord::Base
607
611
  set_primary_key :number_code
612
+
613
+ create_table do
614
+ string 'number_code'
615
+ string 'name'
616
+ string 'census_region_name'
617
+ integer 'census_region_number'
618
+ index 'census_region_name', :name => 'homefry'
619
+ index ['number_code', 'name', 'census_region_name', 'census_region_number']
620
+ end
621
+
608
622
  data_miner do
609
- schema :options => 'ENGINE=InnoDB default charset=utf8' do
610
- string 'number_code'
611
- string 'name'
612
- string 'census_region_name'
613
- integer 'census_region_number'
614
- index 'census_region_name', :name => 'homefry'
615
- index ['number_code', 'name', 'census_region_name', 'census_region_number']
623
+ process "create table" do
624
+ create_table!
616
625
  end
617
626
  end
618
627
  end
619
628
 
620
629
  class CensusDivisionFour < ActiveRecord::Base
630
+ create_table do
631
+ string 'number_code'
632
+ string 'name'
633
+ string 'census_region_name'
634
+ integer 'census_region_number'
635
+ index 'census_region_name', :name => 'homefry'
636
+ end
637
+
621
638
  data_miner do
622
- schema do
623
- string 'number_code'
624
- string 'name'
625
- string 'census_region_name'
626
- integer 'census_region_number'
627
- index 'census_region_name', :name => 'homefry'
639
+ process "create table" do
640
+ create_table!
628
641
  end
629
642
  end
630
643
  end
631
644
 
632
645
  # todo: have somebody properly organize these
633
646
  class TestOldSyntax < Test::Unit::TestCase
634
- # if ENV['WIP']
635
- # context 'with nullify option' do
636
- # should 'treat blank fields as null values' do
637
- # Aircraft.delete_all
638
- # Aircraft.data_miner_runs.delete_all
639
- # Aircraft.run_data_miner!
640
- # assert_greater_than 0, Aircraft.count
641
- # assert_false Aircraft.where(:brighter_planet_aircraft_class_code => nil).empty?
642
- # end
643
- # end
644
- # end
645
- #
646
- # if ENV['ALL'] == 'true'
647
- # should 'directly create a table for the model' do
648
- # if AutomobileMakeFleetYear.table_exists?
649
- # ActiveRecord::Base.connection.execute 'DROP TABLE automobile_make_fleet_years;'
650
- # end
651
- # AutomobileMakeFleetYear.execute_schema
652
- # assert AutomobileMakeFleetYear.table_exists?
653
- # end
654
- # end
655
- #
656
- # if ENV['ALL'] == 'true' or ENV['FAST'] == 'true'
657
- # should 'append to an existing config' do
658
- # AutomobileFuelType.class_eval do
659
- # data_miner :append => true do
660
- # import 'example1', :url => 'http://example1.com' do
661
- # key 'code'
662
- # store 'name'
663
- # end
664
- # end
665
- # data_miner :append => true do
666
- # import 'example2', :url => 'http://example2.com' do
667
- # key 'code'
668
- # store 'name'
669
- # end
670
- # end
671
- # end
672
- # assert_equal 'http://example1.com', AutomobileFuelType.data_miner_config.steps[-2].table.url
673
- # assert_equal 'http://example2.com', AutomobileFuelType.data_miner_config.steps[-1].table.url
674
- # end
675
- #
676
- # should 'override an existing data_miner configuration' do
677
- # AutomobileFuelType.class_eval do
678
- # data_miner do
679
- # import 'example', :url => 'http://example.com' do
680
- # key 'code'
681
- # store 'name'
682
- # end
683
- # end
684
- # end
685
- # assert_kind_of DataMiner::Import, AutomobileFuelType.data_miner_config.steps.first
686
- # assert_equal 'http://example.com', AutomobileFuelType.data_miner_config.steps.first.table.url
687
- # end
688
- # should "stop and finish if it gets a DataMiner::Finish" do
689
- # AutomobileMakeFleetYear.delete_all
690
- # AutomobileMakeFleetYear.data_miner_runs.delete_all
691
- # $force_finish = true
692
- # AutomobileMakeFleetYear.run_data_miner!
693
- # assert_equal 0, AutomobileMakeFleetYear.count
694
- # assert (AutomobileMakeFleetYear.data_miner_runs.count > 0)
695
- # assert AutomobileMakeFleetYear.data_miner_runs.all? { |run| run.finished? and not run.skipped and not run.killed? }
696
- # $force_finish = false
697
- # AutomobileMakeFleetYear.run_data_miner!
698
- # assert AutomobileMakeFleetYear.exists?(:name => 'Alfa Romeo IP 1978')
699
- # end
700
- #
701
- # should "stop and register skipped if it gets a DataMiner::Skip" do
702
- # AutomobileMakeFleetYear.delete_all
703
- # AutomobileMakeFleetYear.data_miner_runs.delete_all
704
- # $force_skip = true
705
- # AutomobileMakeFleetYear.run_data_miner!
706
- # assert_equal 0, AutomobileMakeFleetYear.count
707
- # assert (AutomobileMakeFleetYear.data_miner_runs.count > 0)
708
- # assert AutomobileMakeFleetYear.data_miner_runs.all? { |run| run.skipped? and not run.finished? and not run.killed? }
709
- # $force_skip = false
710
- # AutomobileMakeFleetYear.run_data_miner!
711
- # assert AutomobileMakeFleetYear.exists?(:name => 'Alfa Romeo IP 1978')
712
- # end
713
- #
714
- # should "eagerly enforce a schema" do
715
- # ActiveRecord::Base.connection.create_table 'census_division_trois', :force => true, :options => 'ENGINE=InnoDB default charset=utf8' do |t|
716
- # t.string 'name'
717
- # t.string 'census_region_name'
718
- # # t.integer 'census_region_number'
719
- # end
720
- # ActiveRecord::Base.connection.execute 'ALTER TABLE census_division_trois ADD INDEX (census_region_name)'
721
- # CensusDivisionTrois.reset_column_information
722
- # missing_columns = %w{ census_region_number }
723
- #
724
- # # sanity check
725
- # missing_columns.each do |column|
726
- # assert_false CensusDivisionTrois.column_names.include?(column)
727
- # end
728
- # assert_false ActiveRecord::Base.connection.indexes(CensusDivisionTrois.table_name).any? { |index| index.name == 'homefry' }
729
- #
730
- # 3.times do
731
- # CensusDivisionTrois.run_data_miner!
732
- # missing_columns.each do |column|
733
- # assert CensusDivisionTrois.column_names.include?(column)
734
- # end
735
- # assert ActiveRecord::Base.connection.indexes(CensusDivisionTrois.table_name).any? { |index| index.name == 'homefry' }
736
- # assert_equal :string, CensusDivisionTrois.columns_hash[CensusDivisionTrois.primary_key].type
737
- # end
738
- # end
739
- #
740
- # should "let schemas work with default id primary keys" do
741
- # ActiveRecord::Base.connection.create_table 'census_division_fours', :force => true, :options => 'ENGINE=InnoDB default charset=utf8' do |t|
742
- # t.string 'name'
743
- # t.string 'census_region_name'
744
- # # t.integer 'census_region_number'
745
- # end
746
- # ActiveRecord::Base.connection.execute 'ALTER TABLE census_division_fours ADD INDEX (census_region_name)'
747
- # CensusDivisionFour.reset_column_information
748
- # missing_columns = %w{ census_region_number }
749
- #
750
- # # sanity check
751
- # missing_columns.each do |column|
752
- # assert_false CensusDivisionFour.column_names.include?(column)
753
- # end
754
- # assert_false ActiveRecord::Base.connection.indexes(CensusDivisionFour.table_name).any? { |index| index.name == 'homefry' }
755
- #
756
- # 3.times do
757
- # CensusDivisionFour.run_data_miner!
758
- # missing_columns.each do |column|
759
- # assert CensusDivisionFour.column_names.include?(column)
760
- # end
761
- # assert ActiveRecord::Base.connection.indexes(CensusDivisionFour.table_name).any? { |index| index.name == 'homefry' }
762
- # assert_equal :integer, CensusDivisionFour.columns_hash[CensusDivisionFour.primary_key].type
763
- # end
764
- # end
647
+ if ENV['WIP']
648
+ context 'with nullify option' do
649
+ should 'treat blank fields as null values' do
650
+ Aircraft.delete_all
651
+ Aircraft.data_miner_runs.delete_all
652
+ Aircraft.run_data_miner!
653
+ assert_greater_than 0, Aircraft.count
654
+ assert_false Aircraft.where(:brighter_planet_aircraft_class_code => nil).empty?
655
+ end
656
+ end
657
+ end
658
+
659
+ if ENV['ALL'] == 'true'
660
+ should 'directly create a table for the model' do
661
+ if AutomobileMakeFleetYear.table_exists?
662
+ ActiveRecord::Base.connection.execute 'DROP TABLE automobile_make_fleet_years;'
663
+ end
664
+ AutomobileMakeFleetYear.create_table!
665
+ assert AutomobileMakeFleetYear.table_exists?
666
+ end
667
+ end
668
+
669
+ if ENV['ALL'] == 'true' or ENV['FAST'] == 'true'
670
+ should 'append to an existing config' do
671
+ AutomobileFuelType.class_eval do
672
+ data_miner :append => true do
673
+ import 'example1', :url => 'http://example1.com' do
674
+ key 'code'
675
+ store 'name'
676
+ end
677
+ end
678
+ data_miner :append => true do
679
+ import 'example2', :url => 'http://example2.com' do
680
+ key 'code'
681
+ store 'name'
682
+ end
683
+ end
684
+ end
685
+ assert_equal 'http://example1.com', AutomobileFuelType.data_miner_config.steps[-2].table.url
686
+ assert_equal 'http://example2.com', AutomobileFuelType.data_miner_config.steps[-1].table.url
687
+ end
688
+
689
+ should 'override an existing data_miner configuration' do
690
+ AutomobileFuelType.class_eval do
691
+ data_miner do
692
+ import 'example', :url => 'http://example.com' do
693
+ key 'code'
694
+ store 'name'
695
+ end
696
+ end
697
+ end
698
+ assert_kind_of DataMiner::Import, AutomobileFuelType.data_miner_config.steps.first
699
+ assert_equal 'http://example.com', AutomobileFuelType.data_miner_config.steps.first.table.url
700
+ end
701
+ should "stop and finish if it gets a DataMiner::Finish" do
702
+ AutomobileMakeFleetYear.delete_all
703
+ AutomobileMakeFleetYear.data_miner_runs.delete_all
704
+ $force_finish = true
705
+ AutomobileMakeFleetYear.run_data_miner!
706
+ assert_equal 0, AutomobileMakeFleetYear.count
707
+ assert (AutomobileMakeFleetYear.data_miner_runs.count > 0)
708
+ assert AutomobileMakeFleetYear.data_miner_runs.all? { |run| run.finished? and not run.skipped and not run.killed? }
709
+ $force_finish = false
710
+ AutomobileMakeFleetYear.run_data_miner!
711
+ assert AutomobileMakeFleetYear.exists?(:name => 'Alfa Romeo IP 1978')
712
+ end
713
+
714
+ should "stop and register skipped if it gets a DataMiner::Skip" do
715
+ AutomobileMakeFleetYear.delete_all
716
+ AutomobileMakeFleetYear.data_miner_runs.delete_all
717
+ $force_skip = true
718
+ AutomobileMakeFleetYear.run_data_miner!
719
+ assert_equal 0, AutomobileMakeFleetYear.count
720
+ assert (AutomobileMakeFleetYear.data_miner_runs.count > 0)
721
+ assert AutomobileMakeFleetYear.data_miner_runs.all? { |run| run.skipped? and not run.finished? and not run.killed? }
722
+ $force_skip = false
723
+ AutomobileMakeFleetYear.run_data_miner!
724
+ assert AutomobileMakeFleetYear.exists?(:name => 'Alfa Romeo IP 1978')
725
+ end
726
+
727
+ should "eagerly enforce a schema" do
728
+ ActiveRecord::Base.connection.create_table 'census_division_trois', :force => true, :options => 'ENGINE=InnoDB default charset=utf8' do |t|
729
+ t.string 'name'
730
+ t.string 'census_region_name'
731
+ # t.integer 'census_region_number'
732
+ end
733
+ ActiveRecord::Base.connection.execute 'ALTER TABLE census_division_trois ADD INDEX (census_region_name)'
734
+ CensusDivisionTrois.reset_column_information
735
+ missing_columns = %w{ census_region_number }
736
+
737
+ # sanity check
738
+ missing_columns.each do |column|
739
+ assert_false CensusDivisionTrois.column_names.include?(column)
740
+ end
741
+ assert_false ActiveRecord::Base.connection.indexes(CensusDivisionTrois.table_name).any? { |index| index.name == 'homefry' }
742
+
743
+ 3.times do
744
+ CensusDivisionTrois.run_data_miner!
745
+ missing_columns.each do |column|
746
+ assert CensusDivisionTrois.column_names.include?(column)
747
+ end
748
+ assert ActiveRecord::Base.connection.indexes(CensusDivisionTrois.table_name).any? { |index| index.name == 'homefry' }
749
+ assert_equal :string, CensusDivisionTrois.columns_hash[CensusDivisionTrois.primary_key].type
750
+ end
751
+ end
752
+
753
+ should "let schemas work with default id primary keys" do
754
+ ActiveRecord::Base.connection.create_table 'census_division_fours', :force => true, :options => 'ENGINE=InnoDB default charset=utf8' do |t|
755
+ t.string 'name'
756
+ t.string 'census_region_name'
757
+ # t.integer 'census_region_number'
758
+ end
759
+ ActiveRecord::Base.connection.execute 'ALTER TABLE census_division_fours ADD INDEX (census_region_name)'
760
+ CensusDivisionFour.reset_column_information
761
+ missing_columns = %w{ census_region_number }
762
+
763
+ # sanity check
764
+ missing_columns.each do |column|
765
+ assert_false CensusDivisionFour.column_names.include?(column)
766
+ end
767
+ assert_false ActiveRecord::Base.connection.indexes(CensusDivisionFour.table_name).any? { |index| index.name == 'homefry' }
768
+
769
+ 3.times do
770
+ CensusDivisionFour.run_data_miner!
771
+ missing_columns.each do |column|
772
+ assert CensusDivisionFour.column_names.include?(column)
773
+ end
774
+ assert ActiveRecord::Base.connection.indexes(CensusDivisionFour.table_name).any? { |index| index.name == 'homefry' }
775
+ assert_equal :integer, CensusDivisionFour.columns_hash[CensusDivisionFour.primary_key].type
776
+ end
777
+ end
765
778
 
766
779
  should "allow specifying dictionaries explicitly" do
767
780
  CensusDivisionDeux.run_data_miner!
768
781
  assert_equal 'South Region', CensusDivisionDeux.find(5).census_region_name
769
782
  end
770
783
 
771
- # should "be able to key on things other than the primary key" do
772
- # Aircraft.run_data_miner!
773
- # assert_equal 'SP', Aircraft.find('DHC6').brighter_planet_aircraft_class_code
774
- # end
775
- #
776
- # should "be able to synthesize rows without using a full parser class" do
777
- # AutomobileMakeFleetYear.run_data_miner!
778
- # assert AutomobileMakeFleetYear.exists?(:name => 'Alfa Romeo IP 1978')
779
- # end
780
- #
781
- # should "keep a call stack so that you can call run_data_miner! on a child" do
782
- # CrosscallingCensusDivision.run_data_miner!
783
- # assert CrosscallingCensusDivision.exists? :name => 'Mountain Division', :number => 8, :census_region_number => 4, :census_region_name => 'West Region'
784
- # assert CrosscallingCensusRegion.exists? :name => 'West Region', :number => 4
785
- # end
786
- #
787
- # should "keep a call stack so that you can call run_data_miner! on a parent" do
788
- # CrosscallingCensusRegion.run_data_miner!
789
- # assert CrosscallingCensusDivision.exists? :name => 'Mountain Division', :number => 8, :census_region_number => 4, :census_region_name => 'West Region'
790
- # assert CrosscallingCensusRegion.exists? :name => 'West Region', :number => 4
791
- # end
792
- #
793
- # should "import airports" do
794
- # Airport.run_data_miner!
795
- # assert Airport.count > 0
796
- # end
797
- #
798
- # should "tap airports" do
799
- # TappedAirport.run_data_miner!
800
- # assert TappedAirport.count > 0
801
- # end
802
- #
803
- # should "pull in census divisions using a data.brighterplanet.com dictionary" do
804
- # CensusDivision.run_data_miner!
805
- # assert CensusDivision.count > 0
806
- # end
807
- #
808
- # should "have a way to queue up runs that works with delated_job's send_later" do
809
- # assert AutomobileVariant.respond_to?(:run_data_miner!)
810
- # end
811
- #
812
- # should "be idempotent" do
813
- # Country.data_miner_config.run
814
- # a = Country.count
815
- # Country.data_miner_config.run
816
- # b = Country.count
817
- # assert_equal a, b
818
- #
819
- # CensusRegion.data_miner_config.run
820
- # a = CensusRegion.count
821
- # CensusRegion.data_miner_config.run
822
- # b = CensusRegion.count
823
- # assert_equal a, b
824
- # end
825
- #
826
- # should "hash things" do
827
- # AutomobileVariant.data_miner_config.steps[0].run
828
- # assert AutomobileVariant.first.row_hash.present?
829
- # end
830
- #
831
- # should "process a callback block instead of a method" do
832
- # AutomobileVariant.delete_all
833
- # AutomobileVariant.data_miner_config.steps[0].run
834
- # assert !AutomobileVariant.first.fuel_efficiency_city.present?
835
- # AutomobileVariant.data_miner_config.steps.last.run
836
- # assert AutomobileVariant.first.fuel_efficiency_city.present?
837
- # end
838
- #
839
- # should "keep a log when it does a run" do
840
- # approx_started_at = Time.now
841
- # DataMiner.run :resource_names => %w{ Country }
842
- # approx_terminated_at = Time.now
843
- # last_run = DataMiner::Run.first(:conditions => { :resource_name => 'Country' }, :order => 'id DESC')
844
- # assert (last_run.started_at - approx_started_at).abs < 5 # seconds
845
- # assert (last_run.terminated_at - approx_terminated_at).abs < 5 # seconds
846
- # end
847
- #
848
- # should "request a re-import from scratch" do
849
- # c = Country.new
850
- # c.iso_3166 = 'JUNK'
851
- # c.save!
852
- # assert Country.exists?(:iso_3166 => 'JUNK')
853
- # DataMiner.run :resource_names => %w{ Country }, :from_scratch => true
854
- # assert !Country.exists?(:iso_3166 => 'JUNK')
855
- # end
856
- #
857
- # should "know what runs were on a resource" do
858
- # DataMiner.run :resource_names => %w{ Country }
859
- # DataMiner.run :resource_names => %w{ Country }
860
- # assert Country.data_miner_runs.count > 0
861
- # end
862
- # end
863
- #
864
- # if ENV['ALL'] == 'true' or ENV['SLOW'] == 'true'
865
- # should "allow errata to be specified with a shorthand, assuming the responder is the resource class itself" do
866
- # AircraftDeux.run_data_miner!
867
- # assert AircraftDeux.exists? :icao_code => 'DC91', :bts_aircraft_type_code => '630'
868
- # end
869
- #
870
- # should "mine aircraft" do
871
- # Aircraft.run_data_miner!
872
- # assert Aircraft.exists? :icao_code => 'DC91', :bts_aircraft_type_code => '630'
873
- # end
874
- #
875
- # should "mine automobile variants" do
876
- # AutomobileVariant.run_data_miner!
877
- # assert AutomobileVariant.count('make_name LIKE "%tesla"') > 0
878
- # end
879
- #
880
- # should "mine T100 flight segments" do
881
- # T100FlightSegment.run_data_miner!
882
- # assert T100FlightSegment.count('dest_country_name LIKE "%United States"') > 0
883
- # end
884
- #
885
- # should "mine residence survey responses" do
886
- # ResidentialEnergyConsumptionSurveyResponse.run_data_miner!
887
- # assert ResidentialEnergyConsumptionSurveyResponse.find(6).residence_class.start_with?('Single-family detached house')
888
- # end
889
- # end
890
- # should "mark the run as skipped if verification fails" do
891
- # AutomobileFuelType.data_miner_config.instance_eval do
892
- # verify "failure" do
893
- # false
894
- # end
895
- # end
896
- #
897
- # DataMiner::Run.delete_all
898
- # assert_raise do
899
- # AutomobileFuelType.run_data_miner! :from_scratch => true
900
- # end
901
- # end
784
+ should "be able to key on things other than the primary key" do
785
+ Aircraft.run_data_miner!
786
+ assert_equal 'SP', Aircraft.find('DHC6').brighter_planet_aircraft_class_code
787
+ end
788
+
789
+ should "be able to synthesize rows without using a full parser class" do
790
+ AutomobileMakeFleetYear.run_data_miner!
791
+ assert AutomobileMakeFleetYear.exists?(:name => 'Alfa Romeo IP 1978')
792
+ end
793
+
794
+ should "keep a call stack so that you can call run_data_miner! on a child" do
795
+ CrosscallingCensusDivision.run_data_miner!
796
+ assert CrosscallingCensusDivision.exists? :name => 'Mountain Division', :number => 8, :census_region_number => 4, :census_region_name => 'West Region'
797
+ assert CrosscallingCensusRegion.exists? :name => 'West Region', :number => 4
798
+ end
799
+
800
+ should "keep a call stack so that you can call run_data_miner! on a parent" do
801
+ CrosscallingCensusRegion.run_data_miner!
802
+ assert CrosscallingCensusDivision.exists? :name => 'Mountain Division', :number => 8, :census_region_number => 4, :census_region_name => 'West Region'
803
+ assert CrosscallingCensusRegion.exists? :name => 'West Region', :number => 4
804
+ end
805
+
806
+ should "import airports" do
807
+ Airport.run_data_miner!
808
+ assert Airport.count > 0
809
+ end
810
+
811
+ should "tap airports" do
812
+ TappedAirport.run_data_miner!
813
+ assert TappedAirport.count > 0
814
+ end
815
+
816
+ should "pull in census divisions using a data.brighterplanet.com dictionary" do
817
+ CensusDivision.run_data_miner!
818
+ assert CensusDivision.count > 0
819
+ end
820
+
821
+ should "have a way to queue up runs that works with delated_job's send_later" do
822
+ assert AutomobileVariant.respond_to?(:run_data_miner!)
823
+ end
824
+
825
+ should "be idempotent" do
826
+ Country.data_miner_config.run
827
+ a = Country.count
828
+ Country.data_miner_config.run
829
+ b = Country.count
830
+ assert_equal a, b
831
+
832
+ CensusRegion.data_miner_config.run
833
+ a = CensusRegion.count
834
+ CensusRegion.data_miner_config.run
835
+ b = CensusRegion.count
836
+ assert_equal a, b
837
+ end
838
+
839
+ should "hash things" do
840
+ AutomobileVariant.data_miner_config.steps[0].run
841
+ assert AutomobileVariant.first.row_hash.present?
842
+ end
843
+
844
+ should "process a callback block instead of a method" do
845
+ AutomobileVariant.delete_all
846
+ AutomobileVariant.data_miner_config.steps[0].run
847
+ assert !AutomobileVariant.first.fuel_efficiency_city.present?
848
+ AutomobileVariant.data_miner_config.steps.last.run
849
+ assert AutomobileVariant.first.fuel_efficiency_city.present?
850
+ end
851
+
852
+ should "keep a log when it does a run" do
853
+ approx_started_at = Time.now
854
+ DataMiner.run :resource_names => %w{ Country }
855
+ approx_terminated_at = Time.now
856
+ last_run = DataMiner::Run.first(:conditions => { :resource_name => 'Country' }, :order => 'id DESC')
857
+ assert (last_run.started_at - approx_started_at).abs < 5 # seconds
858
+ assert (last_run.terminated_at - approx_terminated_at).abs < 5 # seconds
859
+ end
860
+
861
+ should "request a re-import from scratch" do
862
+ c = Country.new
863
+ c.iso_3166 = 'JUNK'
864
+ c.save!
865
+ assert Country.exists?(:iso_3166 => 'JUNK')
866
+ DataMiner.run :resource_names => %w{ Country }, :from_scratch => true
867
+ assert !Country.exists?(:iso_3166 => 'JUNK')
868
+ end
869
+
870
+ should "know what runs were on a resource" do
871
+ DataMiner.run :resource_names => %w{ Country }
872
+ DataMiner.run :resource_names => %w{ Country }
873
+ assert Country.data_miner_runs.count > 0
874
+ end
875
+ end
876
+
877
+ if ENV['ALL'] == 'true' or ENV['SLOW'] == 'true'
878
+ should "allow errata to be specified with a shorthand, assuming the responder is the resource class itself" do
879
+ AircraftDeux.run_data_miner!
880
+ assert AircraftDeux.exists? :icao_code => 'DC91', :bts_aircraft_type_code => '630'
881
+ end
882
+
883
+ should "mine aircraft" do
884
+ Aircraft.run_data_miner!
885
+ assert Aircraft.exists? :icao_code => 'DC91', :bts_aircraft_type_code => '630'
886
+ end
887
+
888
+ should "mine automobile variants" do
889
+ AutomobileVariant.run_data_miner!
890
+ assert AutomobileVariant.count('make_name LIKE "%tesla"') > 0
891
+ end
892
+
893
+ should "mine T100 flight segments" do
894
+ T100FlightSegment.run_data_miner!
895
+ assert T100FlightSegment.count('dest_country_name LIKE "%United States"') > 0
896
+ end
897
+
898
+ should "mine residence survey responses" do
899
+ ResidentialEnergyConsumptionSurveyResponse.run_data_miner!
900
+ assert ResidentialEnergyConsumptionSurveyResponse.find(6).residence_class.start_with?('Single-family detached house')
901
+ end
902
+ end
903
+ should "mark the run as skipped if verification fails" do
904
+ AutomobileFuelType.data_miner_config.instance_eval do
905
+ verify "failure" do
906
+ false
907
+ end
908
+ end
909
+
910
+ DataMiner::Run.delete_all
911
+ assert_raise do
912
+ AutomobileFuelType.run_data_miner! :from_scratch => true
913
+ end
914
+ end
902
915
  end
metadata CHANGED
@@ -1,13 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: data_miner
3
3
  version: !ruby/object:Gem::Version
4
- hash: 3
5
4
  prerelease:
6
- segments:
7
- - 1
8
- - 1
9
- - 8
10
- version: 1.1.8
5
+ version: 1.2.0
11
6
  platform: ruby
12
7
  authors:
13
8
  - Seamus Abshere
@@ -17,7 +12,8 @@ autorequire:
17
12
  bindir: bin
18
13
  cert_chain: []
19
14
 
20
- date: 2011-05-06 00:00:00 Z
15
+ date: 2011-06-06 00:00:00 -05:00
16
+ default_executable:
21
17
  dependencies:
22
18
  - !ruby/object:Gem::Dependency
23
19
  name: remote_table
@@ -27,11 +23,6 @@ dependencies:
27
23
  requirements:
28
24
  - - ">="
29
25
  - !ruby/object:Gem::Version
30
- hash: 27
31
- segments:
32
- - 1
33
- - 2
34
- - 2
35
26
  version: 1.2.2
36
27
  type: :runtime
37
28
  version_requirements: *id001
@@ -43,11 +34,6 @@ dependencies:
43
34
  requirements:
44
35
  - - ">="
45
36
  - !ruby/object:Gem::Version
46
- hash: 23
47
- segments:
48
- - 0
49
- - 0
50
- - 4
51
37
  version: 0.0.4
52
38
  type: :runtime
53
39
  version_requirements: *id002
@@ -59,11 +45,6 @@ dependencies:
59
45
  requirements:
60
46
  - - ">="
61
47
  - !ruby/object:Gem::Version
62
- hash: 11
63
- segments:
64
- - 2
65
- - 3
66
- - 4
67
48
  version: 2.3.4
68
49
  type: :runtime
69
50
  version_requirements: *id003
@@ -75,11 +56,6 @@ dependencies:
75
56
  requirements:
76
57
  - - ">="
77
58
  - !ruby/object:Gem::Version
78
- hash: 11
79
- segments:
80
- - 2
81
- - 3
82
- - 4
83
59
  version: 2.3.4
84
60
  type: :runtime
85
61
  version_requirements: *id004
@@ -91,11 +67,6 @@ dependencies:
91
67
  requirements:
92
68
  - - ">="
93
69
  - !ruby/object:Gem::Version
94
- hash: 15
95
- segments:
96
- - 1
97
- - 4
98
- - 4
99
70
  version: 1.4.4
100
71
  type: :runtime
101
72
  version_requirements: *id005
@@ -107,11 +78,6 @@ dependencies:
107
78
  requirements:
108
79
  - - ">="
109
80
  - !ruby/object:Gem::Version
110
- hash: 23
111
- segments:
112
- - 0
113
- - 3
114
- - 2
115
81
  version: 0.3.2
116
82
  type: :runtime
117
83
  version_requirements: *id006
@@ -123,11 +89,6 @@ dependencies:
123
89
  requirements:
124
90
  - - ">="
125
91
  - !ruby/object:Gem::Version
126
- hash: 5
127
- segments:
128
- - 0
129
- - 3
130
- - 11
131
92
  version: 0.3.11
132
93
  type: :runtime
133
94
  version_requirements: *id007
@@ -139,83 +100,61 @@ dependencies:
139
100
  requirements:
140
101
  - - ">="
141
102
  - !ruby/object:Gem::Version
142
- hash: 21
143
- segments:
144
- - 1
145
- - 0
146
- - 1
147
103
  version: 1.0.1
148
104
  type: :runtime
149
105
  version_requirements: *id008
150
106
  - !ruby/object:Gem::Dependency
151
- name: loose_tight_dictionary
107
+ name: create_table
152
108
  prerelease: false
153
109
  requirement: &id009 !ruby/object:Gem::Requirement
154
110
  none: false
155
111
  requirements:
156
112
  - - ">="
157
113
  - !ruby/object:Gem::Version
158
- hash: 21
159
- segments:
160
- - 0
161
- - 0
162
- - 5
163
- version: 0.0.5
114
+ version: 0.0.2
164
115
  type: :development
165
116
  version_requirements: *id009
166
117
  - !ruby/object:Gem::Dependency
167
- name: test-unit
118
+ name: loose_tight_dictionary
168
119
  prerelease: false
169
120
  requirement: &id010 !ruby/object:Gem::Requirement
170
121
  none: false
171
122
  requirements:
172
123
  - - ">="
173
124
  - !ruby/object:Gem::Version
174
- hash: 3
175
- segments:
176
- - 0
177
- version: "0"
125
+ version: 0.0.5
178
126
  type: :development
179
127
  version_requirements: *id010
180
128
  - !ruby/object:Gem::Dependency
181
- name: shoulda
129
+ name: test-unit
182
130
  prerelease: false
183
131
  requirement: &id011 !ruby/object:Gem::Requirement
184
132
  none: false
185
133
  requirements:
186
134
  - - ">="
187
135
  - !ruby/object:Gem::Version
188
- hash: 3
189
- segments:
190
- - 0
191
136
  version: "0"
192
137
  type: :development
193
138
  version_requirements: *id011
194
139
  - !ruby/object:Gem::Dependency
195
- name: mysql
140
+ name: shoulda
196
141
  prerelease: false
197
142
  requirement: &id012 !ruby/object:Gem::Requirement
198
143
  none: false
199
144
  requirements:
200
145
  - - ">="
201
146
  - !ruby/object:Gem::Version
202
- hash: 3
203
- segments:
204
- - 0
205
147
  version: "0"
206
148
  type: :development
207
149
  version_requirements: *id012
208
150
  - !ruby/object:Gem::Dependency
209
- name: ruby-debug
151
+ name: mysql
210
152
  prerelease: false
211
153
  requirement: &id013 !ruby/object:Gem::Requirement
212
154
  none: false
213
155
  requirements:
214
156
  - - ">="
215
157
  - !ruby/object:Gem::Version
216
- hash: 3
217
- segments:
218
- - 0
219
158
  version: "0"
220
159
  type: :development
221
160
  version_requirements: *id013
@@ -245,7 +184,6 @@ files:
245
184
  - lib/data_miner/import.rb
246
185
  - lib/data_miner/process.rb
247
186
  - lib/data_miner/run.rb
248
- - lib/data_miner/schema.rb
249
187
  - lib/data_miner/tap.rb
250
188
  - lib/data_miner/verify.rb
251
189
  - lib/data_miner/version.rb
@@ -260,6 +198,7 @@ files:
260
198
  - test/test_data_miner_process.rb
261
199
  - test/test_data_miner_verify.rb
262
200
  - test/test_old_syntax.rb
201
+ has_rdoc: true
263
202
  homepage: https://github.com/seamusabshere/data_miner
264
203
  licenses: []
265
204
 
@@ -273,23 +212,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
273
212
  requirements:
274
213
  - - ">="
275
214
  - !ruby/object:Gem::Version
276
- hash: 3
277
- segments:
278
- - 0
279
215
  version: "0"
280
216
  required_rubygems_version: !ruby/object:Gem::Requirement
281
217
  none: false
282
218
  requirements:
283
219
  - - ">="
284
220
  - !ruby/object:Gem::Version
285
- hash: 3
286
- segments:
287
- - 0
288
221
  version: "0"
289
222
  requirements: []
290
223
 
291
224
  rubyforge_project: data_miner
292
- rubygems_version: 1.7.2
225
+ rubygems_version: 1.6.2
293
226
  signing_key:
294
227
  specification_version: 3
295
228
  summary: Mine remote data into your ActiveRecord models.
@@ -1,241 +0,0 @@
1
- require 'blockenspiel'
2
- class DataMiner
3
- class Schema
4
- include ::Blockenspiel::DSL
5
-
6
- attr_reader :config
7
- attr_reader :create_table_options
8
-
9
- def initialize(config, create_table_options)
10
- @config = config
11
- @create_table_options = create_table_options.dup
12
- @create_table_options.stringify_keys!
13
- raise "'id' => true is not allowed in create_table_options." if @create_table_options['id'] === true
14
- raise "'primary_key' is not allowed in create_table_options. Use set_primary_key instead." if @create_table_options.has_key?('primary_key')
15
- @create_table_options['id'] = false # always
16
- end
17
-
18
- def resource
19
- config.resource
20
- end
21
-
22
- # sabshere 1/25/11 what if there were multiple connections
23
- # blockenspiel doesn't like to delegate this to #resource
24
- def connection
25
- ::ActiveRecord::Base.connection
26
- end
27
-
28
- def table_name
29
- resource.table_name
30
- end
31
-
32
- def ideal_table
33
- @ideal_table ||= ::ActiveRecord::ConnectionAdapters::TableDefinition.new connection
34
- end
35
-
36
- def ideal_indexes
37
- @ideal_indexes ||= []
38
- end
39
-
40
- def actual_indexes
41
- connection.indexes table_name
42
- end
43
-
44
- def description
45
- "Define a table called #{table_name} with primary key #{ideal_primary_key_name}"
46
- end
47
-
48
- def inspect
49
- %{#<DataMiner::Schema(#{resource}): #{description}>}
50
- end
51
-
52
- # sabshere 1/25/11 lifted straight from activerecord-3.0.3/lib/active_record/connection_adapters/abstract/schema_definitions.rb
53
- %w( string text integer float decimal datetime timestamp time date binary boolean ).each do |column_type|
54
- class_eval <<-EOV
55
- def #{column_type}(*args) # def string(*args)
56
- options = args.extract_options! # options = args.extract_options!
57
- column_names = args # column_names = args
58
- #
59
- column_names.each { |name| ideal_table.column(name, '#{column_type}', options) } # column_names.each { |name| ideal_table.column(name, 'string', options) }
60
- end # end
61
- EOV
62
- end
63
- def column(*args)
64
- ideal_table.column(*args)
65
- end
66
-
67
- MAX_INDEX_NAME_LENGTH = 32
68
- def index(columns, options = {})
69
- options = options.dup
70
- options.stringify_keys!
71
- columns = ::Array.wrap columns
72
- unless name = options['name']
73
- default_name = connection.index_name(table_name, options.symbolize_keys.merge(:column => columns))
74
- name = default_name.length < MAX_INDEX_NAME_LENGTH ? default_name : default_name[0..MAX_INDEX_NAME_LENGTH-11] + ::Zlib.crc32(default_name).to_s
75
- end
76
- index_unique = options.has_key?('unique') ? options['unique'] : true
77
- ideal_indexes.push ::ActiveRecord::ConnectionAdapters::IndexDefinition.new(table_name, name, index_unique, columns)
78
- nil
79
- end
80
-
81
- def ideal_primary_key_name
82
- resource.primary_key.to_s
83
- end
84
-
85
- def actual_primary_key_name
86
- connection.primary_key(table_name).to_s
87
- end
88
-
89
- INDEX_PROPERTIES = %w{ name columns }
90
- def index_equivalent?(a, b)
91
- return false unless a and b
92
- INDEX_PROPERTIES.all? do |property|
93
- ::DataMiner.logger.debug "...comparing #{a.send(property).inspect}.to_s <-> #{b.send(property).inspect}.to_s"
94
- a.send(property).to_s == b.send(property).to_s
95
- end
96
- end
97
-
98
- # FIXME mysql only (assume integer primary keys)
99
- def column_equivalent?(a, b)
100
- return false unless a and b
101
- a_type = a.type.to_s == 'primary_key' ? 'integer' : a.type.to_s
102
- b_type = b.type.to_s == 'primary_key' ? 'integer' : b.type.to_s
103
- a_type == b_type and a.name.to_s == b.name.to_s
104
- end
105
-
106
- %w{ column index }.each do |i|
107
- eval %{
108
- def #{i}_needs_to_be_placed?(name)
109
- actual = actual_#{i} name
110
- return true unless actual
111
- ideal = ideal_#{i} name
112
- not #{i}_equivalent? actual, ideal
113
- end
114
-
115
- def #{i}_needs_to_be_removed?(name)
116
- ideal_#{i}(name).nil?
117
- end
118
- }
119
- end
120
-
121
- def ideal_column(name)
122
- ideal_table[name.to_s]
123
- end
124
-
125
- def actual_column(name)
126
- resource.columns_hash[name.to_s]
127
- end
128
-
129
- def ideal_index(name)
130
- ideal_indexes.detect { |ideal| ideal.name == name.to_s }
131
- end
132
-
133
- def actual_index(name)
134
- actual_indexes.detect { |actual| actual.name == name.to_s }
135
- end
136
-
137
- def place_column(name)
138
- remove_column name if actual_column name
139
- ideal = ideal_column name
140
- ::DataMiner.logger.debug "ADDING COLUMN #{name}"
141
- connection.add_column table_name, name, ideal.type.to_sym # symbol type!
142
- resource.reset_column_information
143
- end
144
-
145
- def remove_column(name)
146
- ::DataMiner.logger.debug "REMOVING COLUMN #{name}"
147
- connection.remove_column table_name, name
148
- resource.reset_column_information
149
- end
150
-
151
- def place_index(name)
152
- remove_index name if actual_index name
153
- ideal = ideal_index name
154
- ::DataMiner.logger.debug "ADDING INDEX #{name}"
155
- connection.add_index table_name, ideal.columns, :name => ideal.name
156
- resource.reset_column_information
157
- end
158
-
159
- def remove_index(name)
160
- ::DataMiner.logger.debug "REMOVING INDEX #{name}"
161
- connection.remove_index table_name, :name => name
162
- resource.reset_column_information
163
- end
164
-
165
- def run
166
- _create_table
167
- _set_primary_key
168
- _remove_columns
169
- _add_columns
170
- _remove_indexes
171
- _add_indexes
172
- nil
173
- end
174
-
175
- def _create_table
176
- if not resource.table_exists?
177
- create_table_options = @create_table_options.dup
178
- create_table_options.symbolize_keys!
179
- ::DataMiner.logger.debug "CREATING TABLE #{table_name} with #{create_table_options.inspect}"
180
- connection.create_table table_name, create_table_options do |t|
181
- t.integer 'data_miner_placeholder'
182
- end
183
- resource.reset_column_information
184
- end
185
- end
186
-
187
- # FIXME mysql only
188
- def _set_primary_key
189
- if ideal_primary_key_name == 'id' and not ideal_column('id')
190
- ::DataMiner.logger.debug "no special primary key set on #{table_name}, so using 'id'"
191
- column 'id', :primary_key # needs to be a sym?
192
- end
193
- actual = actual_column actual_primary_key_name
194
- ideal = ideal_column ideal_primary_key_name
195
- if not column_equivalent? actual, ideal
196
- ::DataMiner.logger.debug "looks like #{table_name} has a bad (or missing) primary key"
197
- if actual
198
- ::DataMiner.logger.debug "looks like primary key needs to change from #{actual_primary_key_name} to #{ideal_primary_key_name}, re-creating #{table_name} from scratch"
199
- connection.drop_table table_name
200
- resource.reset_column_information
201
- _create_table
202
- end
203
- place_column ideal_primary_key_name
204
- unless ideal.type.to_s == 'primary_key'
205
- ::DataMiner.logger.debug "SETTING #{ideal_primary_key_name} AS PRIMARY KEY"
206
- if connection.adapter_name.downcase == 'sqlite'
207
- connection.execute "CREATE UNIQUE INDEX IDX_#{table_name}_#{ideal_primary_key_name} ON #{table_name} (#{ideal_primary_key_name} ASC)"
208
- else
209
- connection.execute "ALTER TABLE `#{table_name}` ADD PRIMARY KEY (`#{ideal_primary_key_name}`)"
210
- end
211
- end
212
- end
213
- resource.reset_column_information
214
- end
215
-
216
- def _remove_columns
217
- resource.columns_hash.values.each do |actual|
218
- remove_column actual.name if column_needs_to_be_removed? actual.name
219
- end
220
- end
221
-
222
- def _add_columns
223
- ideal_table.columns.each do |ideal|
224
- place_column ideal.name if column_needs_to_be_placed? ideal.name
225
- end
226
- end
227
-
228
- def _remove_indexes
229
- actual_indexes.each do |actual|
230
- remove_index actual.name if index_needs_to_be_removed? actual.name
231
- end
232
- end
233
-
234
- def _add_indexes
235
- ideal_indexes.each do |ideal|
236
- next if ideal.name == ideal_primary_key_name # this should already have been taken care of
237
- place_index ideal.name if index_needs_to_be_placed? ideal.name
238
- end
239
- end
240
- end
241
- end