ez_model 1.0.5 → 1.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +3 -52
- data/bin/ezmodel +15 -9
- data/lib/ez_model/version.rb +1 -1
- data/lib/rmre/content.eruby +14 -0
- data/lib/rmre/generator.rb +95 -27
- data/lib/rmre/model.eruby +15 -20
- metadata +2 -1
data/README.md
CHANGED
@@ -1,54 +1,12 @@
|
|
1
1
|
# EZModel
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
It uses [Rmre](https://github.com/bosko/rmre "Rmre") as underlying reverse engine to generate models. I made some modifications to Rmre to support mysql2 adapter, and had those auto-generated model files placed in a subfolder inside ~/app/models/ez_models/ instead of the default ~/app/models/, so that regenerating models will not overwrite the existing ones. Over the times, db schema can ge changed, all it needs is to run the command again to regenerate models, developers can feel free to add methods to the models classes in ~/app/models/ without worrying about being overwritten.
|
6
|
-
|
7
|
-
|
8
|
-
## How it works
|
9
|
-
|
10
|
-
First let's take a look at what it does.
|
11
|
-
|
12
|
-
In ~/app/models/ez_models/, it will generate model files inherit ActiveRecord::Base
|
13
|
-
|
14
|
-
~/app/models/ez_models/billing_info.rb
|
15
|
-
|
16
|
-
# This file is auto-generated from the current state of the database registered
|
17
|
-
# in ~config/database.yml. Instead of editing this file, please go to ~/app/models/
|
18
|
-
# and find the file with same name and class that inherits this class
|
19
|
-
module EZModel
|
20
|
-
module ActiveRecord
|
21
|
-
class BillingInfo < ::ActiveRecord::Base
|
22
|
-
belongs_to :users, :class_name => 'User', :foreign_key => :user_id
|
23
|
-
belongs_to :invoices, :class_name => 'Invoice', :foreign_key => :invoice_id
|
24
|
-
has_many :chargebacks, :class_name => 'Chargeback'
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
Isn't model files supposed to be in ~/app/models/? Take a look at the following first
|
30
|
-
In ~/app/models/, it will generate same model files and inherit the above classes
|
31
|
-
|
32
|
-
~/app/models/billing_info.rb
|
33
|
-
|
34
|
-
require File.expand_path('../ez_models/billing_info', __FILE__)
|
35
|
-
# Please add your own methods to this class.
|
36
|
-
# It's strongly recommended to check this file into your version control system.
|
37
|
-
class BillingInfo < EZModel::ActiveRecord::BillingInfo
|
38
|
-
|
39
|
-
end
|
40
|
-
|
3
|
+
Automatically generate model files from database.
|
41
4
|
|
42
5
|
## How to use it
|
43
6
|
|
44
|
-
###
|
7
|
+
###1. Setup database
|
45
8
|
|
46
|
-
|
47
|
-
|
48
|
-
there are many tools can be use for database design, you can then export scripts to generate db schema;
|
49
|
-
checkout mysql-workbench and its forward-engineering feature for more details about designing ER diagram and generate schema;
|
50
|
-
|
51
|
-
####2. Prepare ~/config/database.yml, here is a sample:
|
9
|
+
###2. Prepare ~/config/database.yml, here is a sample:
|
52
10
|
|
53
11
|
development:
|
54
12
|
adapter: mysql2
|
@@ -89,13 +47,6 @@ or
|
|
89
47
|
|
90
48
|
ezmodel -g -e development
|
91
49
|
|
92
|
-
generate model files and overwrite existing ones in ~/app/models/
|
93
|
-
use this command only if the model files in ~/app/models/ don't inherit EZModel::ActiveRecord
|
94
|
-
backup your models files is strongly suggested if you are not sure what it is doing
|
95
|
-
use it at your own risk
|
96
|
-
|
97
|
-
ezmodel -g -o
|
98
|
-
|
99
50
|
see help
|
100
51
|
|
101
52
|
ezmodel -h
|
data/bin/ezmodel
CHANGED
@@ -5,6 +5,7 @@ $LOAD_PATH.unshift lib unless $LOAD_PATH.include?(lib)
|
|
5
5
|
require "yaml"
|
6
6
|
require "optparse"
|
7
7
|
require "erubis"
|
8
|
+
require "fileutils"
|
8
9
|
require "ez_model"
|
9
10
|
require "rmre"
|
10
11
|
|
@@ -20,11 +21,13 @@ optparse = OptionParser.new do |opts|
|
|
20
21
|
options[:generate] = true
|
21
22
|
end
|
22
23
|
|
24
|
+
=begin
|
23
25
|
options[:overwrite] = false
|
24
26
|
opts.on("-o", "--overwrite",
|
25
27
|
"Overwrite model files (before you do so, back up your models in '~app/models/')") do
|
26
28
|
options[:overwrite] = true
|
27
29
|
end
|
30
|
+
=end
|
28
31
|
|
29
32
|
options[:dbconfig] = "config/database.yml"
|
30
33
|
opts.on("-d", "--dbconfig PATH",
|
@@ -91,8 +94,9 @@ options[:db].merge!(:host => db_config[d_environment]["host"])
|
|
91
94
|
options[:db].merge!(:port => db_config[d_environment]["port"])
|
92
95
|
options[:db][:timeout] = 5000
|
93
96
|
options[:dump_schema] = rails_root_path + "db/schema.rb"
|
94
|
-
options[:out_path] = rails_root_path + "app/models/
|
97
|
+
options[:out_path] = rails_root_path + "app/models/"
|
95
98
|
options[:model_path] = rails_root_path + "app/models/"
|
99
|
+
options[:old_model_path] = rails_root_path + "app/models/ez_models/"
|
96
100
|
|
97
101
|
########################################################################################################
|
98
102
|
# generate ez_models using external rmre
|
@@ -142,9 +146,9 @@ end
|
|
142
146
|
|
143
147
|
if options[:dump_schema]
|
144
148
|
_backup_schema_file = options[:dump_schema]+".bak"
|
145
|
-
if(File.exists?(options[:dump_schema]))
|
146
|
-
|
147
|
-
|
149
|
+
if (File.exists?(options[:dump_schema]))
|
150
|
+
puts "Backing up schema file to #{_backup_schema_file}"
|
151
|
+
File.rename(options[:dump_schema], _backup_schema_file)
|
148
152
|
end
|
149
153
|
puts "Dumping schema to #{options[:dump_schema]}..."
|
150
154
|
File.open(options[:dump_schema], 'w') do |file|
|
@@ -152,15 +156,17 @@ if options[:dump_schema]
|
|
152
156
|
end
|
153
157
|
end
|
154
158
|
|
155
|
-
puts "Generating
|
159
|
+
puts "Generating models in #{options[:out_path]}..."
|
156
160
|
generator.create_models(generator.connection.tables)
|
157
161
|
|
158
162
|
########################################################################################################
|
159
163
|
# generate models
|
160
164
|
########################################################################################################
|
161
165
|
|
162
|
-
puts "Generating models in #{options[:model_path]}..."
|
163
|
-
EZModel::Generator.CreateModels(options[:model_path], generator.connection.tables, options[:overwrite])
|
166
|
+
#puts "Generating models in #{options[:model_path]}..."
|
167
|
+
#EZModel::Generator.CreateModels(options[:model_path], generator.connection.tables, options[:overwrite])
|
168
|
+
|
169
|
+
# remove old base model
|
170
|
+
FileUtils.rm_rf(options[:old_model_path]) if Dir.exists?(options[:old_model_path])
|
164
171
|
|
165
|
-
puts "Congratulations, your schema.rb and
|
166
|
-
puts "Feel free to customize your model in ~/app/models/"
|
172
|
+
puts "Congratulations, your schema.rb and models have been generated"
|
data/lib/ez_model/version.rb
CHANGED
@@ -0,0 +1,14 @@
|
|
1
|
+
##########BEGIN-EZMODEL-AUTO-GENERATED-SECTION##########
|
2
|
+
<% unless table_name == table_name.tableize %>
|
3
|
+
<%= "set_table_name '#{table_name}'" + "\n" -%>
|
4
|
+
<% end %>
|
5
|
+
<% unless "id" == primary_key || primary_key.nil? %>
|
6
|
+
<%= "set_primary_key :#{primary_key}" + "\n" -%>
|
7
|
+
<% end %>
|
8
|
+
<% if has_type_column %>
|
9
|
+
<%= "set_inheritance_column :ruby_type" + "\n" -%>
|
10
|
+
<% end %>
|
11
|
+
<% constraints.each do |constraint| %>
|
12
|
+
<%= constraint + "\n" -%>
|
13
|
+
<% end %>
|
14
|
+
##########END-EZMODEL-AUTO-GENERATED-SECTION##########
|
data/lib/rmre/generator.rb
CHANGED
@@ -10,6 +10,9 @@ module Rmre
|
|
10
10
|
|
11
11
|
SETTINGS_ROOT = File.expand_path('../../../../db', __FILE__)
|
12
12
|
|
13
|
+
BEGIN_TAG = "##########BEGIN-EZMODEL-AUTO-GENERATED-SECTION##########"
|
14
|
+
END_TAG = "##########END-EZMODEL-AUTO-GENERATED-SECTION##########"
|
15
|
+
|
13
16
|
def initialize(options, out_path, include)
|
14
17
|
@connection_options = options
|
15
18
|
@connection = nil
|
@@ -39,16 +42,72 @@ module Rmre
|
|
39
42
|
end
|
40
43
|
|
41
44
|
def create_model(table_name)
|
42
|
-
|
43
|
-
|
45
|
+
constraints = []
|
46
|
+
|
47
|
+
foreign_keys.each do |fk|
|
48
|
+
src = constraint_src(table_name, fk)
|
49
|
+
constraints << src unless src.nil?
|
50
|
+
end
|
51
|
+
|
52
|
+
_file_path = File.join(output_path, "#{table_name.tableize.singularize}.rb")
|
53
|
+
if (!File.exists?(_file_path))
|
54
|
+
content = generate_model_source(table_name, constraints)
|
55
|
+
else
|
56
|
+
|
57
|
+
# read file content
|
58
|
+
file = File.open(_file_path, "r+")
|
59
|
+
content = ""
|
60
|
+
line_begin = -1
|
61
|
+
line_end = -1
|
62
|
+
i = -1
|
63
|
+
while (!file.eof?)
|
64
|
+
i = i+1
|
65
|
+
_line = file.readline
|
66
|
+
|
67
|
+
# remove old code
|
68
|
+
if (_line.include?(table_name.tableize.classify) &&
|
69
|
+
_line.include?("EZModel::ActiveRecord"))
|
70
|
+
_line = "class #{table_name.tableize.classify} < ActiveRecord::Base \n"
|
71
|
+
end
|
72
|
+
|
73
|
+
if (_line.include?(BEGIN_TAG))
|
74
|
+
line_begin = i
|
75
|
+
end
|
76
|
+
if (_line.include?(END_TAG))
|
77
|
+
line_end = i
|
78
|
+
end
|
79
|
+
|
80
|
+
content += _line
|
81
|
+
end
|
82
|
+
file.close()
|
83
|
+
|
84
|
+
# remove auto generated code
|
85
|
+
if (line_begin<line_end)
|
86
|
+
content = content.gsub(/#{BEGIN_TAG}(.*)#{END_TAG}/im, "")
|
87
|
+
end
|
44
88
|
|
45
|
-
|
46
|
-
|
47
|
-
|
89
|
+
_text = content
|
90
|
+
content = ""
|
91
|
+
_text.split("\n").each do |_line|
|
92
|
+
|
93
|
+
# remove include header from old version
|
94
|
+
unless (_line.include?("require File.expand_path('../ez_models"))
|
95
|
+
content += _line + "\n"
|
96
|
+
end
|
97
|
+
|
98
|
+
# add auto-gen code below class
|
99
|
+
if (_line.include?(table_name.tableize.classify) &&
|
100
|
+
_line.include?("ActiveRecord::Base"))
|
101
|
+
_body = generate_model_content(table_name, constraints)
|
102
|
+
content += _body + "\n"
|
103
|
+
end
|
48
104
|
end
|
105
|
+
end
|
49
106
|
|
50
|
-
|
107
|
+
File.open(_file_path, "w") do |file|
|
108
|
+
file.write(content)
|
51
109
|
end
|
110
|
+
|
52
111
|
end
|
53
112
|
|
54
113
|
def process?(table_name)
|
@@ -69,16 +128,16 @@ module Rmre
|
|
69
128
|
def fetch_foreign_keys
|
70
129
|
fk = []
|
71
130
|
case @connection_options[:adapter].downcase
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
131
|
+
when 'mysql'
|
132
|
+
fk = mysql_foreign_keys
|
133
|
+
when 'mysql2'
|
134
|
+
fk = mysql_foreign_keys
|
135
|
+
when 'postgresql'
|
136
|
+
fk = psql_foreign_keys
|
137
|
+
when 'sqlserver'
|
138
|
+
fk = mssql_foreign_keys
|
139
|
+
when 'oracle_enhanced'
|
140
|
+
fk = oracle_foreign_keys
|
82
141
|
end
|
83
142
|
fk
|
84
143
|
end
|
@@ -96,10 +155,19 @@ module Rmre
|
|
96
155
|
def generate_model_source(table_name, constraints)
|
97
156
|
eruby = Erubis::Eruby.new(File.read(File.join(File.expand_path("../", __FILE__), 'model.eruby')))
|
98
157
|
eruby.result(
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
158
|
+
:table_name => table_name,
|
159
|
+
:primary_key => connection.primary_key(table_name),
|
160
|
+
:constraints => constraints,
|
161
|
+
:has_type_column => connection.columns(table_name).find { |col| col.name == 'type' })
|
162
|
+
end
|
163
|
+
|
164
|
+
def generate_model_content(table_name, constraints)
|
165
|
+
eruby = Erubis::Eruby.new(File.read(File.join(File.expand_path("../", __FILE__), 'content.eruby')))
|
166
|
+
eruby.result(
|
167
|
+
:table_name => table_name,
|
168
|
+
:primary_key => connection.primary_key(table_name),
|
169
|
+
:constraints => constraints,
|
170
|
+
:has_type_column => connection.columns(table_name).find { |col| col.name == 'type' })
|
103
171
|
end
|
104
172
|
|
105
173
|
def mysql_foreign_keys
|
@@ -113,7 +181,7 @@ from information_schema.KEY_COLUMN_USAGE
|
|
113
181
|
where referenced_table_schema like '%'
|
114
182
|
and constraint_schema = '#{@connection_options[:database]}'
|
115
183
|
and referenced_table_name is not null
|
116
|
-
SQL
|
184
|
+
SQL
|
117
185
|
connection.select_all(sql)
|
118
186
|
end
|
119
187
|
|
@@ -139,7 +207,7 @@ SELECT tc.table_name as from_table,
|
|
139
207
|
AND rc.unique_constraint_name = ccu.constraint_name
|
140
208
|
WHERE tc.table_name like '%'
|
141
209
|
AND tc.constraint_type = 'FOREIGN KEY';
|
142
|
-
SQL
|
210
|
+
SQL
|
143
211
|
connection.select_all(sql)
|
144
212
|
end
|
145
213
|
|
@@ -164,7 +232,7 @@ FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS C
|
|
164
232
|
AND C2.CONSTRAINT_NAME = KCU2.CONSTRAINT_NAME
|
165
233
|
AND KCU.ORDINAL_POSITION = KCU2.ORDINAL_POSITION
|
166
234
|
WHERE C.CONSTRAINT_TYPE = 'FOREIGN KEY'
|
167
|
-
SQL
|
235
|
+
SQL
|
168
236
|
connection.select_all(sql)
|
169
237
|
end
|
170
238
|
|
@@ -172,10 +240,10 @@ SQL
|
|
172
240
|
fk = []
|
173
241
|
connection.tables.each do |table|
|
174
242
|
connection.foreign_keys(table).each do |oracle_fk|
|
175
|
-
table_fk = {
|
176
|
-
|
177
|
-
|
178
|
-
|
243
|
+
table_fk = {'from_table' => oracle_fk.from_table,
|
244
|
+
'from_column' => oracle_fk.options[:columns][0],
|
245
|
+
'to_table' => oracle_fk.to_table,
|
246
|
+
'to_column' => oracle_fk.options[:references][0]}
|
179
247
|
fk << table_fk
|
180
248
|
end
|
181
249
|
end
|
data/lib/rmre/model.eruby
CHANGED
@@ -1,24 +1,19 @@
|
|
1
|
-
# This file is auto-generated from the current state of the database registered
|
2
|
-
# in ~config/database.yml. Instead of editing this file, please go to ~/app/models/
|
3
|
-
# and find the file with same name and class that inherits this class
|
4
|
-
module EZModel
|
5
|
-
module ActiveRecord
|
6
|
-
class <%= table_name.tableize.classify %> < ::ActiveRecord::Base
|
7
|
-
<% unless table_name == table_name.tableize %>
|
8
|
-
<%= "set_table_name '#{table_name}'" + "\n" -%>
|
9
|
-
<% end %>
|
10
1
|
|
11
|
-
|
12
|
-
|
13
|
-
|
2
|
+
class <%= table_name.tableize.classify %> < ActiveRecord::Base
|
3
|
+
##########BEGIN-EZMODEL-AUTO-GENERATED-SECTION##########
|
4
|
+
<% unless table_name == table_name.tableize %>
|
5
|
+
<%= "set_table_name '#{table_name}'" + "\n" -%>
|
6
|
+
<% end %>
|
7
|
+
<% unless "id" == primary_key || primary_key.nil? %>
|
8
|
+
<%= "set_primary_key :#{primary_key}" + "\n" -%>
|
9
|
+
<% end %>
|
10
|
+
<% if has_type_column %>
|
11
|
+
<%= "set_inheritance_column :ruby_type" + "\n" -%>
|
12
|
+
<% end %>
|
13
|
+
<% constraints.each do |constraint| %>
|
14
|
+
<%= constraint + "\n" -%>
|
15
|
+
<% end %>
|
16
|
+
##########END-EZMODEL-AUTO-GENERATED-SECTION##########
|
14
17
|
|
15
|
-
<% if has_type_column %>
|
16
|
-
<%= "set_inheritance_column :ruby_type" + "\n" -%>
|
17
|
-
<% end %>
|
18
18
|
|
19
|
-
<% constraints.each do |constraint| %>
|
20
|
-
<%= constraint + "\n" -%>
|
21
|
-
<% end %>
|
22
|
-
end
|
23
|
-
end
|
24
19
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ez_model
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.6
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -72,6 +72,7 @@ files:
|
|
72
72
|
- lib/rmre.rb
|
73
73
|
- lib/rmre/LICENSE.txt
|
74
74
|
- lib/rmre/active_record/schema_dumper.rb
|
75
|
+
- lib/rmre/content.eruby
|
75
76
|
- lib/rmre/generator.rb
|
76
77
|
- lib/rmre/load_file.eruby
|
77
78
|
- lib/rmre/model.eruby
|