legacy_data 0.1.12 → 0.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.
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