legacy_data 0.1.12 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. data/.rvmrc +1 -0
  2. data/History.txt +2 -2
  3. data/README.md +6 -4
  4. data/Rakefile +9 -11
  5. data/VERSION +1 -1
  6. data/examples/generated/blog_mysql/factories.rb +3 -3
  7. data/examples/generated/blog_sqlite3/factories.rb +4 -4
  8. data/examples/generated/drupal_mysql/factories.rb +321 -321
  9. data/examples/generated/j2ee_petstore_mysql/factories.rb +39 -39
  10. data/examples/generated/j2ee_petstore_oracle/factories.rb +36 -36
  11. data/examples/generated/j2ee_petstore_sqlite3/factories.rb +39 -39
  12. data/legacy_data.gemspec +4 -3
  13. data/lib/{active_record/connection_adapters/oracleenhanced_adapter.rb → foreigner/connection_adapters/oracle_enhanced_adapter.rb} +0 -0
  14. data/lib/generators/models_from_tables/USAGE +12 -0
  15. data/lib/generators/models_from_tables/models_from_tables_generator.rb +70 -0
  16. data/lib/generators/models_from_tables/templates/model.rb +11 -0
  17. data/lib/legacy_data.rb +6 -7
  18. data/lib/legacy_data/schema.rb +1 -0
  19. data/lib/legacy_data/table_class_name_mapper.rb +4 -2
  20. data/lib/legacy_data/table_definition.rb +1 -2
  21. data/spec/functional/blog_adapterspec.rb +13 -13
  22. data/spec/functional/drupal_adapterspec.rb +14 -12
  23. data/spec/functional/functional_spec_helper.rb +3 -5
  24. data/spec/functional/j2ee_petstore_adapterspec.rb +14 -14
  25. data/spec/generators/models_from_tables/expected/factories.rb +5 -0
  26. data/spec/{expected → generators/models_from_tables/expected}/post.rb +0 -0
  27. data/spec/{models_from_tables_generator_spec.rb → generators/models_from_tables/models_from_tables_generator_spec.rb} +28 -28
  28. data/spec/legacy_data/schema_spec.rb +0 -1
  29. data/spec/legacy_data/table_class_name_mapper_spec.rb +1 -4
  30. data/spec/spec_helper.rb +46 -28
  31. metadata +66 -49
  32. data/generators/models_from_tables/USAGE +0 -6
  33. data/generators/models_from_tables/models_from_tables_generator.rb +0 -78
  34. data/generators/models_from_tables/templates/model.rb +0 -11
  35. data/spec/expected/factories.rb +0 -5
@@ -1,57 +1,57 @@
1
- Factory.define :address do |a|
2
- a.street1 'some string'
3
- a.city 'some string'
4
- a.state 'some string'
5
- a.zip 'some string'
6
- a.latitude 12.3
7
- a.longitude 12.3
1
+ Factory.define :address do |address|
2
+ address.street1 'some string'
3
+ address.city 'some string'
4
+ address.state 'some string'
5
+ address.zip 'some string'
6
+ address.latitude 12.3
7
+ address.longitude 12.3
8
8
  end
9
9
 
10
- Factory.define :seller_contact_info do |s|
11
- s.lastname 'some string'
12
- s.firstname 'some string'
13
- s.email 'some string'
10
+ Factory.define :seller_contact_info do |seller_contact_info|
11
+ seller_contact_info.lastname 'some string'
12
+ seller_contact_info.firstname 'some string'
13
+ seller_contact_info.email 'some string'
14
14
  end
15
15
 
16
- Factory.define :category do |c|
17
- c.name 'some string'
18
- c.description 'some string'
16
+ Factory.define :category do |category|
17
+ category.name 'some string'
18
+ category.description 'some string'
19
19
  end
20
20
 
21
- Factory.define :id_gen do |i|
22
- i.gen_value 7
21
+ Factory.define :id_gen do |id_gen|
22
+ id_gen.gen_value 7
23
23
  end
24
24
 
25
- Factory.define :item do |i|
26
- i.productid 'some string'
27
- i.name 'some string'
28
- i.description 'some string'
29
- i.price 12.3
30
- i.address_addressid 'some string'
31
- i.contactinfo_contactinfoid 'some string'
32
- i.totalscore 7
33
- i.numberofvotes 7
34
- i.disabled 7
25
+ Factory.define :item do |item|
26
+ item.productid 'some string'
27
+ item.name 'some string'
28
+ item.description 'some string'
29
+ item.price 12.3
30
+ item.address_addressid 'some string'
31
+ item.contactinfo_contactinfoid 'some string'
32
+ item.totalscore 7
33
+ item.numberofvotes 7
34
+ item.disabled 7
35
35
  end
36
36
 
37
- Factory.define :product do |p|
38
- p.categoryid 'some string'
39
- p.name 'some string'
40
- p.description 'some string'
37
+ Factory.define :product do |product|
38
+ product.categoryid 'some string'
39
+ product.name 'some string'
40
+ product.description 'some string'
41
41
  end
42
42
 
43
- Factory.define :tag do |t|
44
- t.tag 'some string'
45
- t.refcount 7
43
+ Factory.define :tag do |tag|
44
+ tag.tag 'some string'
45
+ tag.refcount 7
46
46
  end
47
47
 
48
- Factory.define :tag_item do |t|
49
- t.tagid 7
50
- t.itemid 'some string'
48
+ Factory.define :tag_item do |tag_item|
49
+ tag_item.tagid 7
50
+ tag_item.itemid 'some string'
51
51
  end
52
52
 
53
- Factory.define :ziplocation do |z|
54
- z.city 'some string'
55
- z.state 'some string'
53
+ Factory.define :ziplocation do |ziplocation|
54
+ ziplocation.city 'some string'
55
+ ziplocation.state 'some string'
56
56
  end
57
57
 
@@ -1,52 +1,52 @@
1
- Factory.define :address do |a|
2
- a.street1 'some string'
3
- a.city 'some string'
4
- a.state 'some string'
5
- a.zip 'some string'
6
- a.latitude 12.3
7
- a.longitude 12.3
1
+ Factory.define :address do |address|
2
+ address.street1 'some string'
3
+ address.city 'some string'
4
+ address.state 'some string'
5
+ address.zip 'some string'
6
+ address.latitude 12.3
7
+ address.longitude 12.3
8
8
  end
9
9
 
10
- Factory.define :category do |c|
11
- c.name 'some string'
12
- c.description 'some string'
10
+ Factory.define :category do |category|
11
+ category.name 'some string'
12
+ category.description 'some string'
13
13
  end
14
14
 
15
- Factory.define :id_gen do |i|
16
- i.gen_value 7
15
+ Factory.define :id_gen do |id_gen|
16
+ id_gen.gen_value 7
17
17
  end
18
18
 
19
- Factory.define :item do |i|
20
- i.productid 'some string'
21
- i.name 'some string'
22
- i.description 'some string'
23
- i.price 12.3
24
- i.address_addressid 'some string'
25
- i.contactinfo_contactinfoid 'some string'
26
- i.totalscore 7
27
- i.numberofvotes 7
28
- i.disabled 7
19
+ Factory.define :item do |item|
20
+ item.productid 'some string'
21
+ item.name 'some string'
22
+ item.description 'some string'
23
+ item.price 12.3
24
+ item.address_addressid 'some string'
25
+ item.contactinfo_contactinfoid 'some string'
26
+ item.totalscore 7
27
+ item.numberofvotes 7
28
+ item.disabled 7
29
29
  end
30
30
 
31
- Factory.define :product do |p|
32
- p.categoryid 'some string'
33
- p.name 'some string'
34
- p.description 'some string'
31
+ Factory.define :product do |product|
32
+ product.categoryid 'some string'
33
+ product.name 'some string'
34
+ product.description 'some string'
35
35
  end
36
36
 
37
- Factory.define :sellercontactinfo do |s|
38
- s.lastname 'some string'
39
- s.firstname 'some string'
40
- s.email 'some string'
37
+ Factory.define :sellercontactinfo do |sellercontactinfo|
38
+ sellercontactinfo.lastname 'some string'
39
+ sellercontactinfo.firstname 'some string'
40
+ sellercontactinfo.email 'some string'
41
41
  end
42
42
 
43
- Factory.define :tag do |t|
44
- t.tag 'some string'
45
- t.refcount 7
43
+ Factory.define :tag do |tag|
44
+ tag.tag 'some string'
45
+ tag.refcount 7
46
46
  end
47
47
 
48
- Factory.define :ziplocation do |z|
49
- z.city 'some string'
50
- z.state 'some string'
48
+ Factory.define :ziplocation do |ziplocation|
49
+ ziplocation.city 'some string'
50
+ ziplocation.state 'some string'
51
51
  end
52
52
 
@@ -1,57 +1,57 @@
1
- Factory.define :address do |a|
2
- a.street1 'some string'
3
- a.city 'some string'
4
- a.state 'some string'
5
- a.zip 'some string'
6
- a.latitude 12.3
7
- a.longitude 12.3
1
+ Factory.define :address do |address|
2
+ address.street1 'some string'
3
+ address.city 'some string'
4
+ address.state 'some string'
5
+ address.zip 'some string'
6
+ address.latitude 12.3
7
+ address.longitude 12.3
8
8
  end
9
9
 
10
- Factory.define :seller_contact_info do |s|
11
- s.lastname 'some string'
12
- s.firstname 'some string'
13
- s.email 'some string'
10
+ Factory.define :seller_contact_info do |seller_contact_info|
11
+ seller_contact_info.lastname 'some string'
12
+ seller_contact_info.firstname 'some string'
13
+ seller_contact_info.email 'some string'
14
14
  end
15
15
 
16
- Factory.define :category do |c|
17
- c.name 'some string'
18
- c.description 'some string'
16
+ Factory.define :category do |category|
17
+ category.name 'some string'
18
+ category.description 'some string'
19
19
  end
20
20
 
21
- Factory.define :id_gen do |i|
22
- i.gen_value 7
21
+ Factory.define :id_gen do |id_gen|
22
+ id_gen.gen_value 7
23
23
  end
24
24
 
25
- Factory.define :item do |i|
26
- i.productid 'some string'
27
- i.name 'some string'
28
- i.description 'some string'
29
- i.price 12.3
30
- i.address_addressid 'some string'
31
- i.contactinfo_contactinfoid 'some string'
32
- i.totalscore 7
33
- i.numberofvotes 7
34
- i.disabled 7
25
+ Factory.define :item do |item|
26
+ item.productid 'some string'
27
+ item.name 'some string'
28
+ item.description 'some string'
29
+ item.price 12.3
30
+ item.address_addressid 'some string'
31
+ item.contactinfo_contactinfoid 'some string'
32
+ item.totalscore 7
33
+ item.numberofvotes 7
34
+ item.disabled 7
35
35
  end
36
36
 
37
- Factory.define :product do |p|
38
- p.categoryid 'some string'
39
- p.name 'some string'
40
- p.description 'some string'
37
+ Factory.define :product do |product|
38
+ product.categoryid 'some string'
39
+ product.name 'some string'
40
+ product.description 'some string'
41
41
  end
42
42
 
43
- Factory.define :tag do |t|
44
- t.tag 'some string'
45
- t.refcount 7
43
+ Factory.define :tag do |tag|
44
+ tag.tag 'some string'
45
+ tag.refcount 7
46
46
  end
47
47
 
48
- Factory.define :tag_item do |t|
49
- t.tagid 7
50
- t.itemid 'some string'
48
+ Factory.define :tag_item do |tag_item|
49
+ tag_item.tagid 7
50
+ tag_item.itemid 'some string'
51
51
  end
52
52
 
53
- Factory.define :ziplocation do |z|
54
- z.city 'some string'
55
- z.state 'some string'
53
+ Factory.define :ziplocation do |ziplocation|
54
+ ziplocation.city 'some string'
55
+ ziplocation.state 'some string'
56
56
  end
57
57
 
@@ -16,11 +16,12 @@ Gem::Specification.new do |s|
16
16
  s.rdoc_options = ["--charset=UTF-8"]
17
17
  s.require_path = "lib"
18
18
 
19
- s.add_dependency 'activerecord', '~> 2.3.5'
19
+ s.add_dependency 'railties', '~> 3.0.1'
20
+ s.add_dependency 'activerecord', '~> 3.0.1'
21
+ s.add_dependency 'activesupport', '~> 3.0.1'
20
22
  s.add_dependency 'foreigner', '~> 0.9.1'
21
23
 
22
24
  s.add_development_dependency 'rake', '~> 0.8.7'
23
- s.add_development_dependency 'rspec', '~> 1.3.1'
25
+ s.add_development_dependency 'rspec', '~> 2.1.0'
24
26
  s.add_development_dependency 'sqlite3-ruby', '~> 1.3.1'
25
- s.add_development_dependency 'rails', '~> 2.3.5'
26
27
  end
@@ -0,0 +1,12 @@
1
+ Description:
2
+ Creates models for existing tables in a legacy database
3
+
4
+ Example:
5
+ rails generate models_from_tables
6
+
7
+ This will create:
8
+ an active record model for each table in your database
9
+ a factory for each model in spec/factories.rb
10
+ a temporary file showing the table name/class name mappings its using in app/models/table_mappings.yml
11
+
12
+
@@ -0,0 +1,70 @@
1
+ class ModelsFromTablesGenerator < Rails::Generators::Base
2
+ source_root File.expand_path('../templates', __FILE__)
3
+
4
+ argument :table_name, :type => :string, :required=>false, :default => nil
5
+
6
+ class_option :table_naming_convention, :type => :string, :default => '*',
7
+ :desc => 'Is there a prefix and/or suffix in the table names to strip when creating class names'
8
+ class_option :with_factories, :type => :boolean, :default => true,
9
+ :desc => 'Generate a FactoryGirl factory for each model'
10
+ class_option :skip_associated, :type => :boolean, :default => false,
11
+ :desc => "Do not follow database relations to other tables"
12
+
13
+ # check_class_collision #:suffix => "ControllerTest"
14
+
15
+ def generate_models_from_tables
16
+ LegacyData::TableClassNameMapper.naming_convention = options[:table_naming_convention]
17
+
18
+ analyzed_tables = LegacyData::Schema.analyze(:table_name=>table_name, :skip_associated=>options[:skip_associated])
19
+
20
+ unless analyzed_tables.blank?
21
+ spec_dir_exists = File.exist? "#{Rails.root}/spec"
22
+
23
+ LegacyData::TableClassNameMapper.let_user_validate_dictionary
24
+
25
+ analyzed_tables.each do |analyzed_table|
26
+ analyzed_table.class_name = LegacyData::TableClassNameMapper.class_name_for(analyzed_table[:table_name])
27
+
28
+ # m.class_collisions :class_path, analyzed_table[:class_name]
29
+ @definition = analyzed_table
30
+ template 'model.rb', File.join('app/models', "#{analyzed_table[:class_name].underscore}.rb")
31
+
32
+ add_factory_girl_factory analyzed_table if options[:with_factories] && spec_dir_exists
33
+ end
34
+ end
35
+ end
36
+
37
+ private
38
+ def add_factory_girl_factory analyzed_schema
39
+ factory_name = analyzed_schema[:class_name].underscore
40
+ columns = analyzed_schema[:columns]
41
+
42
+ File.open("#{Rails.root}/spec/factories.rb", 'a+') do |file|
43
+ file.write "Factory.define :#{factory_name} do |#{factory_name}|\n"
44
+ column_with_longest_name = columns.max {|a,b| a.name.length <=> b.name.length }
45
+ columns.each do |c|
46
+ if c.null == false && c.name != analyzed_schema[:primary_key]
47
+ value = case c.type
48
+ when :integer then %[7]
49
+ when :float then %[12.3]
50
+ when :decimal then %[12.3]
51
+ when :datetime then %[{Time.now}]
52
+ when :date then %[{Time.now}]
53
+ when :timestamp then %[{Time.now}]
54
+ when :time then %[{Time.now}]
55
+ when :text then %['some text value']
56
+ when :string then %['some string']
57
+ when :binary then %['some binary stuff']
58
+ when :boolean then %[false]
59
+ else
60
+ "'Sorry the models_to_tables_generator is not sure how to default columns of type #{c.type}'"
61
+ end
62
+ spaces = column_with_longest_name.name.size - c.name.size
63
+ file.write " #{factory_name}.#{c.name}#{' ' * spaces} #{value}\n"
64
+ end
65
+ end
66
+ file.write "end\n\n"
67
+ end
68
+ end
69
+
70
+ end
@@ -0,0 +1,11 @@
1
+ class <%= @definition.class_name -%> < ActiveRecord::Base
2
+ <%= " set_table_name #{@definition.table_name.downcase.to_sym.inspect}\n" if @definition.unconventional_table_name? -%>
3
+ <%= " set_primary_key #{@definition.primary_key.to_sym.inspect}\n" if @definition.unconventional_primary_key? -%>
4
+
5
+ # Relationships
6
+ <%= @definition.relationships_to_s %>
7
+
8
+ # Constraints
9
+ <%= @definition.constraints_to_s %>
10
+ end
11
+
@@ -4,12 +4,11 @@ require 'legacy_data/table_definition'
4
4
  require 'legacy_data/schema'
5
5
  require 'legacy_data/table_class_name_mapper'
6
6
 
7
- module ActiveRecord
8
- Base.class_eval do
9
- if ['OracleEnhanced'].include? connection.adapter_name
10
- # require "#{File.dirname(__FILE__)}/active_record/connection_adapters/#{connection.adapter_name.underscore}_adapter"
11
- require "#{File.dirname(__FILE__)}/active_record/connection_adapters/#{connection.adapter_name.downcase}_adapter"
12
- end
7
+ Foreigner.register 'oracle_enhanced', 'foreigner/connection_adapters/oracle_enhanced_adapter'
8
+
9
+ module LegacyData
10
+ # In Rails 2.3 this was ActiveRecord::Base.class_name but it no longer exists in Rails 3
11
+ def self.conventional_class_name table_name
12
+ table_name.underscore.downcase.pluralize.camelize.singularize
13
13
  end
14
14
  end
15
-
@@ -109,6 +109,7 @@ module LegacyData
109
109
 
110
110
  belongs_to = {}
111
111
  connection.foreign_keys(table_name).each do |foreign_key|
112
+ col = foreign_key.options[:column] || foreign_key.options[:columns].first
112
113
  options = {:foreign_key=>foreign_key.options[:column].downcase.to_sym}
113
114
  options[:dependent] = :destroy if foreign_key.options[:dependent] == :delete
114
115
  belongs_to[foreign_key.to_table.downcase] = options
@@ -1,3 +1,5 @@
1
+ require 'singleton'
2
+
1
3
  module LegacyData
2
4
  class TableClassNameMapper
3
5
  include Singleton
@@ -43,7 +45,7 @@ Done analyzing the tables.
43
45
  end
44
46
 
45
47
  def dictionary_file_name
46
- File.join(RAILS_ROOT, 'app', 'models', 'table_mappings.yml')
48
+ File.join(Rails.root, 'app', 'models', 'table_mappings.yml')
47
49
  end
48
50
 
49
51
  def class_name_for table_name
@@ -57,7 +59,7 @@ Done analyzing the tables.
57
59
  def compute_class_name table_name
58
60
  table_name =~ /#{naming_convention}/i
59
61
  stripped_table_name = $1 || table_name
60
- dictionary[table_name] = ActiveRecord::Base.class_name(stripped_table_name.underscore.downcase.pluralize)
62
+ dictionary[table_name] = LegacyData.conventional_class_name stripped_table_name
61
63
  end
62
64
 
63
65
  def self.log msg