alexrothenberg-legacy_data 0.0.1 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +30 -1
- data/VERSION +1 -1
- data/generators/{legacy_models → models_from_tables}/USAGE +0 -0
- data/generators/models_from_tables/models_from_tables_generator.rb +35 -0
- data/generators/{legacy_models → models_from_tables}/templates/model.rb +4 -3
- data/legacy_data.gemspec +5 -5
- data/lib/legacy_data/schema.rb +11 -5
- data/spec/legacy_data_schema_spec.rb +20 -4
- metadata +5 -5
- data/generators/legacy_models/legacy_models_generator.rb +0 -22
data/README.rdoc
CHANGED
@@ -2,8 +2,37 @@
|
|
2
2
|
|
3
3
|
How can you start a rails project on top of a large legacy database ... use the legacy_data plugin.
|
4
4
|
|
5
|
-
|
5
|
+
What if the database doesn't follow Rails/ActiveRecord naming conventions? ... not a problem
|
6
|
+
What if there are a lot of tables? ... not a problem
|
7
|
+
What about all the information contained in the database already (relationships, constraints, etc) ... they are extracted into your models
|
8
|
+
|
9
|
+
Usage: script/generate models_from_tables [options]
|
10
|
+
--table-name [ARG] Only generate models for tables starting with
|
11
|
+
--table-naming-convention [ARG]
|
12
|
+
Naming convention for tables in the database. Only the wildcard is used when generating the model name
|
13
|
+
|
14
|
+
Examples:
|
15
|
+
* script/generate script/generate models_from_tables --table-naming-convention=tb*
|
16
|
+
Generate a model for each table in the database. The tables all start with a tb (i.e. table 'tbperson' will generate the model 'person')
|
17
|
+
* script/generate script/generate models_from_tables --table-name tbperson
|
18
|
+
Generate a model for the 'tbperson' table in the database.
|
6
19
|
|
20
|
+
== Usage
|
21
|
+
|
22
|
+
* Create a new rails project with the admin data plugin
|
23
|
+
rails my_application -m http://gist.github.com/188172.txt
|
24
|
+
* Configure your application to connect to your existing Oracle database. Get the connect connect string from your dba (something like: user/password@server.example.com:1541/sid.world) and edit your config/database.yml
|
25
|
+
development:
|
26
|
+
adapter: oracle_enhanced
|
27
|
+
database: server.example.com:1541/sid.world
|
28
|
+
username: user
|
29
|
+
password: password
|
30
|
+
* Generate models for all existing tables
|
31
|
+
script/generate models_for_all
|
32
|
+
* Take a look
|
33
|
+
script/server
|
34
|
+
http://localhost:3000/admin_data
|
35
|
+
|
7
36
|
== Note on Patches/Pull Requests
|
8
37
|
|
9
38
|
* Fork the project.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.6
|
File without changes
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../lib/legacy_data/schema'
|
2
|
+
require File.dirname(__FILE__) + '/../../lib/active_record/connection_adapters/oracle_enhanced_adapter'
|
3
|
+
|
4
|
+
class ModelsFromTablesGenerator < Rails::Generator::Base
|
5
|
+
def manifest
|
6
|
+
record do |m|
|
7
|
+
m.directory File.join('app/models')
|
8
|
+
|
9
|
+
if options[:table_name]
|
10
|
+
tables = [options[:table_name] ]
|
11
|
+
else
|
12
|
+
naming_convention = options[:table_naming_convention] || '*'
|
13
|
+
tables = LegacyData::Schema.tables(/^#{naming_convention.gsub('*', '.*')}$/)
|
14
|
+
end
|
15
|
+
tables.each do |table_name|
|
16
|
+
puts "analyzing #{table_name}"
|
17
|
+
analysis = LegacyData::Schema.new(table_name, options[:table_naming_convention]).analyze_table
|
18
|
+
|
19
|
+
file_name = analysis[:class_name].underscore
|
20
|
+
m.template 'model.rb',
|
21
|
+
File.join('app/models', "#{file_name}.rb"),
|
22
|
+
:assigns => analysis
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
def add_options!(opt)
|
29
|
+
opt.on('--table-name [ARG]',
|
30
|
+
'Only generate models for given table') { |value| options[:table_name] = value }
|
31
|
+
opt.on('--table-naming-convention [ARG]',
|
32
|
+
'Naming convention for tables in the database - will not be used when generating naming the models') { |value| options[:table_naming_convention] = value }
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
class <%= class_name -%> < ActiveRecord::Base
|
2
2
|
set_table_name :<%= table_name %>
|
3
|
-
set_primary_key
|
3
|
+
<%= "set_primary_key #{primary_key.inspect}" if primary_key %>
|
4
4
|
|
5
5
|
# Relationships
|
6
6
|
<%- relations[:has_some].each do |class_name, foreign_key|
|
@@ -15,11 +15,12 @@ class <%= class_name -%> < ActiveRecord::Base
|
|
15
15
|
<%- constraints[:multi_column_unique].each do |cols|
|
16
16
|
-%> #validates_uniqueness_of_multiple_column_constraint :<%= cols.inspect %>
|
17
17
|
<%- end -%>
|
18
|
-
<%= "validates_presence_of #{constraints[:non_nullable].map {|cols| cols.
|
18
|
+
<%= "validates_presence_of #{constraints[:non_nullable].map {|cols| cols.downcase.to_sym.inspect}.join(', ')}" unless constraints[:non_nullable].blank? %>
|
19
19
|
<%- constraints[:custom].each do |name, sql_rule|
|
20
20
|
-%> validate <%= "validate_#{name}".to_sym.inspect %>
|
21
21
|
def <%= "validate_#{name}" %>
|
22
|
-
# TODO: validate this SQL constraint
|
22
|
+
# TODO: validate this SQL constraint
|
23
|
+
"<%= sql_rule %>"
|
23
24
|
end
|
24
25
|
<%- end %>
|
25
26
|
end
|
data/legacy_data.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{legacy_data}
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.6"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Alex Rothenberg"]
|
12
|
-
s.date = %q{2009-09-
|
12
|
+
s.date = %q{2009-09-17}
|
13
13
|
s.description = %q{Create ActiveRecord models from an existing database}
|
14
14
|
s.email = %q{alex@alexrothenberg.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -23,9 +23,9 @@ Gem::Specification.new do |s|
|
|
23
23
|
"README.rdoc",
|
24
24
|
"Rakefile",
|
25
25
|
"VERSION",
|
26
|
-
"generators/
|
27
|
-
"generators/
|
28
|
-
"generators/
|
26
|
+
"generators/models_from_tables/USAGE",
|
27
|
+
"generators/models_from_tables/models_from_tables_generator.rb",
|
28
|
+
"generators/models_from_tables/templates/model.rb",
|
29
29
|
"legacy_data.gemspec",
|
30
30
|
"lib/active_record/connection_adapters/oracle_enhanced_adapter.rb",
|
31
31
|
"lib/legacy_data.rb",
|
data/lib/legacy_data/schema.rb
CHANGED
@@ -2,8 +2,10 @@ module LegacyData
|
|
2
2
|
class Schema
|
3
3
|
attr_reader :table_name
|
4
4
|
|
5
|
-
def initialize(table_name)
|
6
|
-
@table_name
|
5
|
+
def initialize(table_name, naming_convention=nil)
|
6
|
+
@table_name = table_name
|
7
|
+
@naming_convention = naming_convention
|
8
|
+
@naming_convention = /^#{naming_convention.gsub('*', '(.*)')}$/i if @naming_convention.is_a? String
|
7
9
|
end
|
8
10
|
|
9
11
|
def analyze_table
|
@@ -16,7 +18,7 @@ module LegacyData
|
|
16
18
|
end
|
17
19
|
|
18
20
|
def self.tables name_pattern=/.*/
|
19
|
-
connection.tables.select {|table_name| table_name =~ name_pattern }
|
21
|
+
connection.tables.select {|table_name| table_name =~ name_pattern }.sort
|
20
22
|
end
|
21
23
|
|
22
24
|
|
@@ -26,7 +28,9 @@ module LegacyData
|
|
26
28
|
end
|
27
29
|
|
28
30
|
def class_name_for table
|
29
|
-
|
31
|
+
table =~ @naming_convention
|
32
|
+
stripped_table_name = $1 || table
|
33
|
+
ActiveRecord::Base.class_name(stripped_table_name.downcase.pluralize)
|
30
34
|
end
|
31
35
|
|
32
36
|
def primary_key
|
@@ -71,8 +75,10 @@ module LegacyData
|
|
71
75
|
end
|
72
76
|
|
73
77
|
def non_nullable_constraints
|
74
|
-
connection.columns(table_name, "#{table_name} Columns").reject(&:null).map(&:name)
|
78
|
+
non_nullable_constraints = connection.columns(table_name, "#{table_name} Columns").reject(&:null).map(&:name)
|
79
|
+
non_nullable_constraints.reject {|col| col == primary_key}
|
75
80
|
end
|
81
|
+
|
76
82
|
def unique_constraints
|
77
83
|
connection.indexes(table_name).select(&:unique).map(&:columns)
|
78
84
|
end
|
@@ -46,6 +46,20 @@ describe LegacyData::Schema do
|
|
46
46
|
it 'should handle tables with an irregular pluralization name' do
|
47
47
|
@schema.class_name_for('TBPERSON').should == 'Tbperson'
|
48
48
|
end
|
49
|
+
|
50
|
+
describe 'ignore the table prefix naming convention when figuring out the model name' do
|
51
|
+
before :each do
|
52
|
+
@schema = LegacyData::Schema.new('some_table', /^TB(.*)$/)
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'should strip off the prefix' do
|
56
|
+
@schema.class_name_for('TBPERSON').should == 'Person'
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should work on tables that do not have the prefix' do
|
60
|
+
@schema.class_name_for('PERSON').should == 'Person'
|
61
|
+
end
|
62
|
+
end
|
49
63
|
|
50
64
|
it 'should have the correct primary_key' do
|
51
65
|
@connection.should_receive(:pk_and_sequence_for).with('some_table').and_return(['PK', 'SEQ'])
|
@@ -76,11 +90,13 @@ describe LegacyData::Schema do
|
|
76
90
|
|
77
91
|
it 'should have the correct constraints'
|
78
92
|
|
79
|
-
it 'should get non-nullable constraints' do
|
93
|
+
it 'should get non-nullable constraints as all columns that do not allow null except the primary key' do
|
94
|
+
@schema.stub(:primary_key).and_return('col1')
|
80
95
|
@connection.should_receive(:columns).with('some_table', 'some_table Columns').and_return([col1=stub(:null=>false, :name=>'col1'),
|
81
|
-
col2=stub(:null=>
|
82
|
-
col3=stub(:null=>
|
83
|
-
|
96
|
+
col2=stub(:null=>false, :name=>'col2'),
|
97
|
+
col3=stub(:null=>true, :name=>'col3'),
|
98
|
+
col3=stub(:null=>false, :name=>'col4')])
|
99
|
+
@schema.non_nullable_constraints.should == ['col2', 'col4']
|
84
100
|
end
|
85
101
|
|
86
102
|
it 'should get uniqueness constraints' do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: alexrothenberg-legacy_data
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alex Rothenberg
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-09-
|
12
|
+
date: 2009-09-17 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -48,9 +48,9 @@ files:
|
|
48
48
|
- README.rdoc
|
49
49
|
- Rakefile
|
50
50
|
- VERSION
|
51
|
-
- generators/
|
52
|
-
- generators/
|
53
|
-
- generators/
|
51
|
+
- generators/models_from_tables/USAGE
|
52
|
+
- generators/models_from_tables/models_from_tables_generator.rb
|
53
|
+
- generators/models_from_tables/templates/model.rb
|
54
54
|
- legacy_data.gemspec
|
55
55
|
- lib/active_record/connection_adapters/oracle_enhanced_adapter.rb
|
56
56
|
- lib/legacy_data.rb
|
@@ -1,22 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/../../lib/legacy_data/schema'
|
2
|
-
require File.dirname(__FILE__) + '/../../lib/active_record/connection_adapters/oracle_enhanced_adapter'
|
3
|
-
|
4
|
-
class LegacyModelsGenerator < Rails::Generator::Base
|
5
|
-
def manifest
|
6
|
-
record do |m|
|
7
|
-
m.directory File.join('app/models')
|
8
|
-
|
9
|
-
LegacyData::Schema.tables(/^tb/).each do |table_name|
|
10
|
-
puts "analyzing #{table_name}"
|
11
|
-
analysis = LegacyData::Schema.new(table_name).analyze_table
|
12
|
-
|
13
|
-
file_name = analysis[:class_name].underscore
|
14
|
-
m.template 'model.rb',
|
15
|
-
File.join('app/models', "#{file_name}.rb"),
|
16
|
-
:assigns => analysis
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
|
22
|
-
end
|