alexrothenberg-legacy_data 0.0.1 → 0.0.6
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 +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
|