data_miner 1.1.8 → 1.2.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.
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