rafaelp-dbdesigner_migration_generator 0.1.1
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/MIT-LICENSE +20 -0
- data/README.mkdn +48 -0
- data/Rakefile +22 -0
- data/dbdesigner_migration_generator.rb +366 -0
- data/templates/dbdesigner_migration.rb +43 -0
- data/test/dbdesigner_migration_generator_test.rb +8 -0
- data/test/test_helper.rb +4 -0
- metadata +66 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2008 Rafael Lima (http://rafael.adm.br)
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.mkdn
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# DBDesigner Migration Generator
|
2
|
+
|
3
|
+
## DESCRIPTION
|
4
|
+
|
5
|
+
This gem generates ActiveRecord Migration files from a DB Designer 4 xml file.
|
6
|
+
|
7
|
+
## REQUIREMENTS
|
8
|
+
|
9
|
+
* activerecord
|
10
|
+
|
11
|
+
## INSTALLATION
|
12
|
+
|
13
|
+
$ sudo gem sources -a http://gems.github.com (you only have to do this once)
|
14
|
+
$ sudo gem install rafaelp-dbdesigner_migration_generator
|
15
|
+
|
16
|
+
Inset line below in your *config/environments/development.rb*
|
17
|
+
|
18
|
+
require 'dbdesigner_migration_generator'
|
19
|
+
|
20
|
+
## USAGE
|
21
|
+
|
22
|
+
Save you model in *db/dbdesigner_model.xml*, then run:
|
23
|
+
|
24
|
+
$ ruby script/generate dbdesigner_migration [MigrationName] [only|except] [table1] [table2] [table3]
|
25
|
+
|
26
|
+
### Example 1
|
27
|
+
|
28
|
+
$ ruby script/generate dbdesigner_migration CompleteDatabase
|
29
|
+
|
30
|
+
### Example 2
|
31
|
+
|
32
|
+
$ ruby script/generate dbdesigner_migration CreateAccountsAndUsers only accounts users
|
33
|
+
|
34
|
+
### Example 3
|
35
|
+
|
36
|
+
$ ruby script/generate dbdesigner_migration CreateOtherTables except accounts users
|
37
|
+
|
38
|
+
### Tricks
|
39
|
+
|
40
|
+
You can put the magical keyword *ignore* on first line of table comments, on your model at DB Designer, to automatically ignore the table on migration generation.
|
41
|
+
|
42
|
+
## LICENSE
|
43
|
+
|
44
|
+
DBDesigner Migration Generator is released under the MIT License.
|
45
|
+
|
46
|
+
## AUTHOR
|
47
|
+
|
48
|
+
[Rafael Lima](http://rafael.adm.br) at [BielSystems](http://bielsystems.com.br) and [Myfreecomm](http://myfreecomm.com.br)
|
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
desc 'Default: run unit tests.'
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
desc 'Test the dbdesigner_migration_generator plugin.'
|
9
|
+
Rake::TestTask.new(:test) do |t|
|
10
|
+
t.libs << 'lib'
|
11
|
+
t.pattern = 'test/**/*_test.rb'
|
12
|
+
t.verbose = true
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'Generate documentation for the dbdesigner_migration_generator plugin.'
|
16
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
17
|
+
rdoc.rdoc_dir = 'rdoc'
|
18
|
+
rdoc.title = 'DbdesignerMigrationGenerator'
|
19
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
20
|
+
rdoc.rdoc_files.include('README')
|
21
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
22
|
+
end
|
@@ -0,0 +1,366 @@
|
|
1
|
+
require 'rails_generator'
|
2
|
+
require 'getoptlong'
|
3
|
+
require 'rexml/document'
|
4
|
+
|
5
|
+
class DbdesignerMigrationGenerator < Rails::Generator::NamedBase
|
6
|
+
|
7
|
+
attr_accessor :migration_name, :tables, :relations
|
8
|
+
|
9
|
+
def manifest
|
10
|
+
@migration_name = class_name
|
11
|
+
|
12
|
+
if args.include? "except" and args.include? "only"
|
13
|
+
raise "It is not possible to use 'except' and 'only' parameters togheter. Try again."
|
14
|
+
end
|
15
|
+
|
16
|
+
@tables = []
|
17
|
+
track = nil
|
18
|
+
args.each do |arg|
|
19
|
+
@tables << arg unless track.nil?
|
20
|
+
arg = arg.to_sym
|
21
|
+
track = arg if arg.eql? :except or arg.eql? :only
|
22
|
+
end
|
23
|
+
|
24
|
+
if track.eql? :except
|
25
|
+
puts "Ignoring table(s) #{@tables.join(',')}\n"
|
26
|
+
DBDesignerMigration::Model.ignore_tables = @tables
|
27
|
+
elsif track.eql? :only
|
28
|
+
puts "Processing only table(s) #{@tables.join(',')}\n"
|
29
|
+
DBDesignerMigration::Model.only_tables = @tables
|
30
|
+
end
|
31
|
+
|
32
|
+
begin
|
33
|
+
dbmodel_path = File.join('db', 'dbdesigner_model.xml')
|
34
|
+
unless File.exist?(dbmodel_path)
|
35
|
+
raise "Could not find any database model in db/dbdesigner_model.xml"
|
36
|
+
end
|
37
|
+
|
38
|
+
xml = REXML::Document.new(File.open(dbmodel_path))
|
39
|
+
|
40
|
+
# Verify that this is a DBDesigner XML file
|
41
|
+
if xml.elements['DBMODEL'].nil? or xml.elements['DBMODEL'].attributes["Version"] != '4.0'
|
42
|
+
raise "File '#{dbmodel_path}' is not a DBDesigner 4 XML file. Skipping..."
|
43
|
+
else
|
44
|
+
puts "Reading the datamodel XML (#{dbmodel_path}) from DBDesigner..." if not $silent
|
45
|
+
xml.elements.each("//DATATYPE") { |d| DBDesignerMigration::Model.add_datatype(d) }
|
46
|
+
xml.elements.each("//TABLE") { |t| DBDesignerMigration::Model.add_table(t) }
|
47
|
+
xml.elements.each("//RELATION") { |r| DBDesignerMigration::Model.add_relation(r) }
|
48
|
+
end
|
49
|
+
rescue Exception => ex
|
50
|
+
puts ex.message
|
51
|
+
puts ex.backtrace.find {|str| str =~ /\.rb/ } || ""
|
52
|
+
exit(1)
|
53
|
+
end
|
54
|
+
|
55
|
+
@tables = DBDesignerMigration::Model.tables
|
56
|
+
@tables.delete_if {|table| table.ignore? }
|
57
|
+
|
58
|
+
@relations = DBDesignerMigration::Model.relations
|
59
|
+
@relations.delete_if {|relation| relation.from_table.ignore? or relation.to_table.ignore? }
|
60
|
+
|
61
|
+
if @tables.empty? and @relations.empty?
|
62
|
+
puts "Nothing to do!"
|
63
|
+
exit(0)
|
64
|
+
end
|
65
|
+
|
66
|
+
record do |m|
|
67
|
+
m.directory File.join('db')
|
68
|
+
m.migration_template 'dbdesigner_migration.rb',"db/migrate", :migration_file_name => "#{file_path}"
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
module DBDesignerMigration
|
76
|
+
|
77
|
+
class Model
|
78
|
+
@datatypes = []
|
79
|
+
@tables = []
|
80
|
+
@relations = []
|
81
|
+
@only_tables = nil
|
82
|
+
@ignore_tables = nil
|
83
|
+
|
84
|
+
def self.only_tables=(tables)
|
85
|
+
@only_tables = tables
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.ignore_tables=(tables)
|
89
|
+
@ignore_tables = tables
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.datatypes
|
93
|
+
@datatypes
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.tables
|
97
|
+
@tables
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.relations
|
101
|
+
@relations
|
102
|
+
end
|
103
|
+
|
104
|
+
def self.add_datatype(xmlobj)
|
105
|
+
id = xmlobj.attributes['ID']
|
106
|
+
name = xmlobj.attributes['TypeName']
|
107
|
+
|
108
|
+
if(@datatypes.find {|d| d.id == id})
|
109
|
+
raise "Duplicate datatype definition on #{name}"
|
110
|
+
end
|
111
|
+
|
112
|
+
@datatypes << Datatype.new(xmlobj)
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.add_table(xmlobj)
|
116
|
+
id = xmlobj.attributes['ID']
|
117
|
+
name = xmlobj.attributes['TableName']
|
118
|
+
|
119
|
+
if(@tables.find {|t| t.id == id})
|
120
|
+
raise "Duplicate table definition on #{name}"
|
121
|
+
end
|
122
|
+
|
123
|
+
@tables << Table.new(xmlobj)
|
124
|
+
end
|
125
|
+
|
126
|
+
def self.add_relation(xmlobj)
|
127
|
+
id = xmlobj.attributes['ID']
|
128
|
+
name = xmlobj.attributes['RelationName']
|
129
|
+
|
130
|
+
if(@relations.find {|t| t.id == id})
|
131
|
+
raise "Duplicate table definition on #{name}"
|
132
|
+
end
|
133
|
+
|
134
|
+
@relations << Relation.new(xmlobj)
|
135
|
+
end
|
136
|
+
|
137
|
+
=begin
|
138
|
+
PREPARED TO USE FOR MODELS
|
139
|
+
|
140
|
+
def self.add_relationship(r)
|
141
|
+
src_table = @tables.find {|t| t.id == r.attributes['SrcTable']}
|
142
|
+
dest_table = @tables.find {|t| t.id == r.attributes['DestTable']}
|
143
|
+
|
144
|
+
relationship = r.attributes['RelationName']
|
145
|
+
if relationship =~ /\s*habtm\s*:(\w+)/
|
146
|
+
relationship = " has_and_belongs_to_many :#{$1}"
|
147
|
+
else
|
148
|
+
# If we are inserting the other side of a relationship (non-habtm),
|
149
|
+
# we need to mirror the relationship.
|
150
|
+
# NOTE: in the DB model, links should be labeled 'has_one' or 'has_many'
|
151
|
+
# not 'belongs_to' since that label is ambiguous 1:1 or 1:n
|
152
|
+
if relationship =~ /has_one/ or relationship =~ /has_many/
|
153
|
+
dest_table.relationships << ' belongs_to :' + src_table.name
|
154
|
+
else relationship !~ /has_and_belongs_to_many/
|
155
|
+
puts "error: relationships must be labeled 'has_one :x', 'has_many :x', 'habtm :x' or 'has_and_belongs_to_many :x'"
|
156
|
+
return
|
157
|
+
end
|
158
|
+
relationship = ' ' + relationship
|
159
|
+
end
|
160
|
+
src_table.relationships << relationship
|
161
|
+
end
|
162
|
+
=end
|
163
|
+
def self.format_options(options)
|
164
|
+
return if options.empty?
|
165
|
+
|
166
|
+
formatted = ""
|
167
|
+
options.each do |k,v|
|
168
|
+
if v.is_a? Symbol
|
169
|
+
formatted << ", :#{k} => :#{v}"
|
170
|
+
elsif v.is_a? String
|
171
|
+
formatted << ", :#{k} => '#{v}'"
|
172
|
+
else
|
173
|
+
formatted << ", :#{k} => #{v}"
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
formatted
|
178
|
+
end
|
179
|
+
|
180
|
+
protected
|
181
|
+
def self.include_table?(table_name)
|
182
|
+
return ((!@only_tables.nil? and @only_tables.include? table_name) or (@only_tables.nil? and @ignore_tables.nil?) or (!@ignore_tables.nil? and !@ignore_tables.include? table_name))
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
class Datatype
|
187
|
+
attr_accessor :id, :name, :description, :physical
|
188
|
+
|
189
|
+
def initialize(xmlobj)
|
190
|
+
@id = xmlobj.attributes['ID']
|
191
|
+
@name = @physical = xmlobj.attributes['TypeName'].downcase
|
192
|
+
@description = xmlobj.attributes['Description']
|
193
|
+
@physical = xmlobj.attributes['PhysicalTypeName'].downcase if not xmlobj.attributes['PhysicalTypeName'].empty?
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
class Table
|
198
|
+
attr_accessor :id, :name, :comments, :columns, :indexes, :relationships, :options, :references
|
199
|
+
|
200
|
+
alias_method :fields, :columns
|
201
|
+
|
202
|
+
def initialize(xmlobj)
|
203
|
+
@id = xmlobj.attributes['ID']
|
204
|
+
@name = xmlobj.attributes['Tablename']
|
205
|
+
@comments = xmlobj.attributes['Comments'].split("\\n")
|
206
|
+
@columns = []
|
207
|
+
@indexes = []
|
208
|
+
@relationships = []
|
209
|
+
@references = []
|
210
|
+
@options = {}
|
211
|
+
@process = ((Model.include_table? @name) and (@comments.empty? or @comments.first.downcase.strip != "ignore"))
|
212
|
+
|
213
|
+
if @name == @name.singularize
|
214
|
+
puts "Warning: table #{@name} is not in plural\n"
|
215
|
+
end
|
216
|
+
|
217
|
+
xmlobj.elements.each("COLUMNS/COLUMN") { |c| self.add_column(c) }
|
218
|
+
xmlobj.elements.each("INDICES/INDEX") { |i| self.add_index(i) }
|
219
|
+
end
|
220
|
+
|
221
|
+
def process?
|
222
|
+
@process
|
223
|
+
end
|
224
|
+
|
225
|
+
def ignore?
|
226
|
+
!@process
|
227
|
+
end
|
228
|
+
|
229
|
+
def add_column(xmlobj)
|
230
|
+
id = xmlobj.attributes['ID']
|
231
|
+
name = xmlobj.attributes['ColName']
|
232
|
+
if("id" == name.downcase)
|
233
|
+
return
|
234
|
+
end
|
235
|
+
|
236
|
+
if(@columns.find {|c| c.id == id})
|
237
|
+
raise "Duplicate column definition on #{self.name} #{name}"
|
238
|
+
end
|
239
|
+
|
240
|
+
@columns << Column.new(xmlobj)
|
241
|
+
end
|
242
|
+
|
243
|
+
def add_index(xmlobj)
|
244
|
+
id = xmlobj.attributes['ID']
|
245
|
+
name = xmlobj.attributes['IndexName']
|
246
|
+
|
247
|
+
xmlobj.elements.each("INDEXCOLUMNS/INDEXCOLUMN") { |i|
|
248
|
+
if(self.columns.find {|c| c.id == i.attributes['idColumn']}.nil?)
|
249
|
+
return
|
250
|
+
end
|
251
|
+
}
|
252
|
+
|
253
|
+
if(@indexes.find {|i| i.id == id})
|
254
|
+
raise "Duplicate index definition on #{self.name} #{name} (#{id})"
|
255
|
+
end
|
256
|
+
|
257
|
+
@indexes << Index.new(self, xmlobj)
|
258
|
+
end
|
259
|
+
|
260
|
+
def add_references(reference)
|
261
|
+
@references << reference
|
262
|
+
end
|
263
|
+
|
264
|
+
end
|
265
|
+
|
266
|
+
class Column
|
267
|
+
attr_accessor :id, :name, :datatype, :params, :notnull, :default, :comments, :options
|
268
|
+
|
269
|
+
def initialize(xmlobj)
|
270
|
+
@id = xmlobj.attributes['ID']
|
271
|
+
@name = xmlobj.attributes['ColName']
|
272
|
+
@datatype = Model.datatypes.find {|c| c.id == xmlobj.attributes['idDatatype']}.physical
|
273
|
+
@params = xmlobj.attributes['DatatypeParams']
|
274
|
+
@notnull = xmlobj.attributes['NotNull']
|
275
|
+
@default = xmlobj.attributes['DefaultValue']
|
276
|
+
@comments = xmlobj.attributes['Comments']
|
277
|
+
@comments = "# #{@comments.split("\\n").join(', ')}" unless @comments.empty?
|
278
|
+
|
279
|
+
options = {}
|
280
|
+
options['default'] = @default unless @default.empty?
|
281
|
+
options['null'] = ("1" == @notnull) ? false : true
|
282
|
+
if not @params.empty?
|
283
|
+
if float = /\(([0-9]+),([0-9]+)\)/.match(@params)
|
284
|
+
options['precision'] = float[1].to_i
|
285
|
+
options['scale'] = float[2].to_i
|
286
|
+
else
|
287
|
+
options['limit'] = /\(([0-9]*)\)/.match(@params)[1].to_i
|
288
|
+
end
|
289
|
+
end
|
290
|
+
# @options['limit'] = (eval(@params) rescue nil) if not @params.empty?
|
291
|
+
|
292
|
+
@options = Model.format_options(options)
|
293
|
+
|
294
|
+
end
|
295
|
+
|
296
|
+
end
|
297
|
+
|
298
|
+
class Index
|
299
|
+
attr_accessor :id, :table, :name, :columns, :unique, :options
|
300
|
+
|
301
|
+
def initialize(table, xmlobj)
|
302
|
+
@id = xmlobj.attributes['ID']
|
303
|
+
@name = xmlobj.attributes['IndexName']
|
304
|
+
@table = table.name
|
305
|
+
columns = Array.new
|
306
|
+
xmlobj.elements.each("INDEXCOLUMNS/INDEXCOLUMN") { |i|
|
307
|
+
columns << table.columns.find {|c| c.id == i.attributes['idColumn']}.name
|
308
|
+
}
|
309
|
+
@columns = "[:#{columns.join(',:')}]" unless columns.nil?
|
310
|
+
@unique = xmlobj.attributes['IndexKind'] == "2"
|
311
|
+
if @unique
|
312
|
+
options = {}
|
313
|
+
options['unique'] = @unique
|
314
|
+
@options = Model.format_options(options)
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
class Relation
|
320
|
+
attr_accessor :id, :name, :from_table, :from_column, :to_table, :to_column, :options
|
321
|
+
|
322
|
+
def initialize(xmlobj)
|
323
|
+
# DBDesigner codes
|
324
|
+
# 0 = restrict
|
325
|
+
# 1 = cascade
|
326
|
+
# 2 = set null
|
327
|
+
# 3 = no action
|
328
|
+
# 4 = set default
|
329
|
+
@dbdesigner_codes = ['restrict','cascade','set null','no action','set default']
|
330
|
+
|
331
|
+
@id = xmlobj.attributes['ID']
|
332
|
+
@name = xmlobj.attributes['RelationName'].downcase
|
333
|
+
@from_table = Model.tables.find {|t| t.id == xmlobj.attributes['DestTable']}
|
334
|
+
@to_table = Model.tables.find {|t| t.id == xmlobj.attributes['SrcTable']}
|
335
|
+
fields = xmlobj.attributes['FKFields'].strip.split("=")
|
336
|
+
@from_column = fields[1].match(/([a-zA-Z_-])*/).to_s
|
337
|
+
@to_column = fields[0].match(/([a-zA-Z_-])*/).to_s
|
338
|
+
|
339
|
+
options = {}
|
340
|
+
|
341
|
+
on_delete = xmlobj.attributes['RefDef'].match(/OnDelete=([0-4]{1})/)
|
342
|
+
if on_delete
|
343
|
+
@on_delete = @dbdesigner_codes[on_delete[1].to_i]
|
344
|
+
options['on_delete'] = @on_delete unless on_delete[1] == '3'
|
345
|
+
end
|
346
|
+
|
347
|
+
on_update = xmlobj.attributes['RefDef'].match(/OnUpdate=([0-4]{1})/)
|
348
|
+
if on_update
|
349
|
+
@on_update = @dbdesigner_codes[on_update[1].to_i]
|
350
|
+
options['on_update'] = @on_update unless on_update[1] == '3'
|
351
|
+
end
|
352
|
+
@options = Model.format_options(options)
|
353
|
+
|
354
|
+
if(@from_table.process? and @to_table.process?)
|
355
|
+
if (@from_column == 'parent_id' and @from_table.name != @to_table.name) or
|
356
|
+
(@from_column != 'parent_id' and @from_column != "#{@to_table.name.singularize}_#{@to_column}")
|
357
|
+
puts "Warning: foreign_key #{@from_table.name}.#{@from_column} => #{@to_table.name}.#{@to_column}\n"
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
@from_table.add_references(@to_table) if @to_column.eql? 'id'
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
end
|
366
|
+
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'postgresql_migrations'
|
2
|
+
|
3
|
+
<% tables.each do |table| -%>
|
4
|
+
# script/generate rspec_model -c --skip-migration <%= table.name.camelize %> <% table.references.each do |table| -%><%= table.name %>:reference <% end -%> <% table.fields.each do |field| -%><%= "#{field.name}:#{field.datatype}" %> <% end -%>
|
5
|
+
|
6
|
+
<% end -%>
|
7
|
+
|
8
|
+
class <%= migration_name.underscore.camelize %> < ActiveRecord::Migration
|
9
|
+
def self.up<% tables.each do |table| -%>
|
10
|
+
<% table.comments.each do |comment| -%>
|
11
|
+
<%= "\# #{comment}" %>
|
12
|
+
<% end -%>
|
13
|
+
|
14
|
+
create_table "<%= table.name %>"<% table.options.each do |k,v| %>, :<%= k %> => <%= v %><% end %>, :force => true do |t|
|
15
|
+
<% table.fields.each do |field| -%>
|
16
|
+
t.<%= field.datatype %> "<%= field.name %>" <%= field.options %> <%= field.comments %>
|
17
|
+
<% end -%>
|
18
|
+
t.timestamps
|
19
|
+
end
|
20
|
+
|
21
|
+
<% table.indexes.sort_by {|index| index.table.to_s}.each do |index| -%>
|
22
|
+
<%= "add_index :#{index.table}, #{index.columns} #{index.options}" %>
|
23
|
+
<% end -%>
|
24
|
+
<% end -%>
|
25
|
+
|
26
|
+
<% relations.each do |relation| -%>
|
27
|
+
<%= "add_foreign_key :#{relation.from_table.name}, :#{relation.from_column}, :#{relation.to_table.name}, :#{relation.to_column} #{relation.options}" %>
|
28
|
+
<% end -%>
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.down
|
32
|
+
<% relations.each do |relation| -%>
|
33
|
+
<%= "remove_foreign_key :#{relation.from_table.name}, :#{relation.from_column}" %>
|
34
|
+
<% end -%>
|
35
|
+
<% tables.sort_by {|table| table.name.to_s }.each do |table| -%>
|
36
|
+
<% table.indexes.sort_by {|index| index.table.to_s}.each do |index| -%>
|
37
|
+
<%= "remove_index :#{index.table}, #{index.columns}" %>
|
38
|
+
<% end -%>
|
39
|
+
<%= "drop_table :#{table.name}" %>
|
40
|
+
<% end -%>
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rafaelp-dbdesigner_migration_generator
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Rafael Lima
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-09-19 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: activerecord
|
17
|
+
version_requirement:
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ">"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.0.0
|
23
|
+
version:
|
24
|
+
description:
|
25
|
+
email: contato@rafael.adm.br
|
26
|
+
executables: []
|
27
|
+
|
28
|
+
extensions: []
|
29
|
+
|
30
|
+
extra_rdoc_files:
|
31
|
+
- README.mkdn
|
32
|
+
files:
|
33
|
+
- MIT-LICENSE
|
34
|
+
- Rakefile
|
35
|
+
- README.mkdn
|
36
|
+
- dbdesigner_migration_generator.rb
|
37
|
+
- templates/dbdesigner_migration.rb
|
38
|
+
has_rdoc: true
|
39
|
+
homepage: http://rafael.adm.br
|
40
|
+
post_install_message:
|
41
|
+
rdoc_options: []
|
42
|
+
|
43
|
+
require_paths:
|
44
|
+
- .
|
45
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: "0"
|
50
|
+
version:
|
51
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: "0"
|
56
|
+
version:
|
57
|
+
requirements: []
|
58
|
+
|
59
|
+
rubyforge_project:
|
60
|
+
rubygems_version: 1.2.0
|
61
|
+
signing_key:
|
62
|
+
specification_version: 2
|
63
|
+
summary: Generates ActiveRecord Migration files from a DB Designer 4 xml file.
|
64
|
+
test_files:
|
65
|
+
- test/test_helper.rb
|
66
|
+
- test/dbdesigner_migration_generator_test.rb
|