Skip to content

Instantly share code, notes, and snippets.

@realityforge
Created September 30, 2013 06:28
Show Gist options
  • Select an option

  • Save realityforge/6760015 to your computer and use it in GitHub Desktop.

Select an option

Save realityforge/6760015 to your computer and use it in GitHub Desktop.
Simple bit of code to convert an old rails style schema dump to a domgen architecture.rb
# Output of:
# ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, File.new("Output.rb","wb") )
output_filename = "architecture.rb"
output = File.new(output_filename, "wb")
def pascal_case(camel_cased_word)
word_parts = split_into_words(camel_cased_word).collect { |part| part[0...1].upcase + part[1..-1] }.collect { |v| v.upcase == 'ID' ? 'ID' : v }
return word_parts[0] if (word_parts.size == 1 && word_parts[0] == word_parts[0].upcase)
word_parts.join('')
end
def split_into_words(camel_cased_word)
word = camel_cased_word.to_s.dup
word.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
word.tr!("-", "_")
word.split("_")
end
def last(s, limit = 1)
return s if limit > s.to_s.size
s.to_s[-limit, limit]
end
def singularize(string)
#in case someone passes in a Symbol instead
plural = string.to_s
if last(plural, 3) == "ies"
return "#{plural[0, plural.size - 3]}y"
elsif last(plural, 4) == "sses" || last(plural, 3) == "oes"
return plural[0, plural.size - 2]
elsif last(plural, 1) == "s"
return plural[0, plural.size - 1]
else
plural
end
end
def referenced_type(name)
pascal_name = pascal_case(name)
candidate_entity_name = pascal_name[0, pascal_name.size - 2]
if pascal_name && name =~ /_id$/ && TYPES[candidate_entity_name]
candidate_entity_name
else
nil
end
end
repository_key = 'CWN'
module_key = 'CWN'
output.write <<-HEADER
Domgen.repository(:#{repository_key}) do |repository|
repository.enable_facet(:sql)
repository.data_module(:Web) do |data_module|
data_module.entity(:Session) do |t|
t.integer(:id, :primary_key => true)
t.string(:session_id, 255)
t.text(:data, :nullable => true)
t.datetime(:created_at, :nullable => true)
t.datetime(:updated_at, :nullable => true)
t.sql.index([:session_id])
t.sql.index([:updated_at])
end
end
repository.data_module(:#{module_key}) do |data_module|
data_module.sql.schema = 'dbo'
HEADER
TYPES = {}
f = IO.read('Output.rb')
# This file is auto-generated from the current state of the database. Instead of editing this file,
f.gsub!(/^#[^\n]*\n/m) do
''
end
f.gsub!(/^ActiveRecord::Schema.define\(:version => \d+\) do$/) do
''
end
f.gsub!(/^ *end\n *\n *add_index/m) do
"\n add_index"
end
f.gsub!(/(add_index [^\n]+)[\n| ]+create_table/m) do
"\n #{$1}\n end\n\n create_table"
end
f.gsub!(/(add_index [^\n]+)[\n| ]+end/m) do
"\n #{$1}\n end\n"
end
f.gsub!(/^ *create_table +"([^"]*)", *:force *=> *true *do *\|t\|[^\n]*$/) do
entity_name = pascal_case(singularize($1))
TYPES[entity_name] = {}
" data_module.entity(:#{entity_name}) do |t|\n t.integer(:ID, :primary_key => true)"
end
f.gsub!(/add_index ".*", \[(.*)\], :name => ".*", :unique => true/) do
keys = $1.tr('"', '').split(',').collect do |s|
name = s.strip
":#{referenced_type(name) || pascal_case(name)}"
end.join(",")
" t.sql.index([#{keys}], :unique => true)"
end
f.gsub!(/add_index ".*", \[(.*)\], :name => ".*"/) do
keys = $1.tr('"', '').split(',').collect do |s|
name = s.strip
":#{referenced_type(name) || pascal_case(name)}"
end.join(",")
" t.sql.index([#{keys}])"
end
def integer_column(name, is_nullable, default_value = nil)
nullable_option = is_nullable ? ', :nullable => true' : ''
default_value_option = default_value ? ", :\"sql.default_value\" => #{default_value}" : ''
pname = pascal_case(name)
type = referenced_type(name)
if type
name_option = pname[0, pname.size - 2] == type ? '' : ", :name => #{pname}"
return " t.reference(:#{type}#{name_option}#{nullable_option})"
end
" t.integer(:#{pname}#{default_value_option}#{nullable_option})"
end
f.gsub!(/^ *t\.integer +\"(.*)\", *:limit *=> *\d+, *:null => false$/) do
integer_column($1, false)
end
f.gsub!(/^ *t\.integer +\"(.*)\", *:limit *=> *\d+$/) do
integer_column($1, true)
end
f.gsub!(/^ *t\.integer +\"(.*)\", *:limit *=> *\d+, *:default => (\d+), *:null => false$/) do
integer_column($1, false, $2)
end
f.gsub!(/^ *t\.integer +\"(.*)\", *:limit *=> *\d+, *:default => (\d+)$/) do
integer_column($1, true, $2)
end
def string_column(name, size, is_nullable, default_value = nil)
nullable_option = is_nullable ? ', :nullable => true' : ''
default_value_option = default_value ? ", :\"sql.default_value\" => #{default_value}" : ''
pname = pascal_case(name)
" t.string(:#{pname}, #{size}#{default_value_option}#{nullable_option})"
end
f.gsub!(/^ *t\.string +\"(.*)\", *:limit *=> *(\d+), *:null => false$/) do
string_column($1, $2, false)
end
f.gsub!(/^ *t\.string +\"(.*)\", *:null => false$/) do
string_column($1, 255, false)
end
f.gsub!(/^ *t\.string +\"(.*)\", *:limit *=> *(\d+)$/) do
string_column($1, $2, true)
end
f.gsub!(/^ *t\.string +\"(.*)\"$/) do
string_column($1, 255, true)
end
def text_column(name, is_nullable, default_value = nil)
nullable_option = is_nullable ? ', :nullable => true' : ''
default_value_option = default_value ? ", :\"sql.default_value\" => #{default_value}" : ''
pname = pascal_case(name)
" t.text(:#{pname}#{default_value_option}#{nullable_option})"
end
f.gsub!(/^ *t\.text +\"(.*)\", *:null => false$/) do
text_column($1, false)
end
f.gsub!(/^ *t\.text +\"(.*)\"$/) do
text_column($1, true)
end
def boolean_column(name, is_nullable, default_value = nil)
nullable_option = is_nullable ? ', :nullable => true' : ''
default_value_option = default_value ? ", :\"sql.default_value\" => #{default_value == 'true' ? "'1'" : "'0'"}" : ''
pname = pascal_case(name)
" t.boolean(:#{pname}#{default_value_option}#{nullable_option})"
end
f.gsub!(/^ *t\.boolean +\"(.*)\", *:default => (true|false), *:null => false$/) do
boolean_column($1, false, $2)
end
f.gsub!(/^ *t\.boolean +\"(.*)\", *:null => false$/) do
boolean_column($1, false)
end
f.gsub!(/^ *t\.boolean +\"(.*)\", *:default => (true|false)$/) do
boolean_column($1, true, $2)
end
f.gsub!(/^ *t\.boolean +\"(.*)\"$/) do
boolean_column($1, true)
end
def real_column(name, is_nullable)
nullable_option = is_nullable ? ', :nullable => true' : ''
pname = pascal_case(name)
" t.real(:#{pname}#{nullable_option})"
end
f.gsub!(/^ *t\.decimal +\"(.*)\",.*:null => false$/) do
real_column($1, false)
end
f.gsub!(/^ *t\.decimal +\"(.*)\".*$/) do
real_column($1, true)
end
def date_column(name, is_nullable)
nullable_option = is_nullable ? ', :nullable => true' : ''
pname = pascal_case(name)
" t.date(:#{pname}#{nullable_option})"
end
f.gsub!(/^ *t\.date +\"(.*)\",.*:null => false$/) do
date_column($1, false)
end
f.gsub!(/^ *t\.date +\"(.*)\".*$/) do
date_column($1, true)
end
def datetime_column(name, is_nullable)
nullable_option = is_nullable ? ', :nullable => true' : ''
pname = pascal_case(name)
" t.datetime(:#{pname}#{nullable_option})"
end
f.gsub!(/^ *t\.datetime +\"(.*)\",.*:null => false$/) do
datetime_column($1, false)
end
f.gsub!(/^ *t\.datetime +\"(.*)\".*$/) do
datetime_column($1, true)
end
f.gsub!(/\n *\n/m) do
"\n"
end
#
#f.gsub!(/\n *\n/m) do
# "\n"
#end
output.write f
output.write <<-FOOTER
data_module.entities.each do |t|
t.sql.table_name = Domgen::Naming.underscore(Domgen::Naming.pluralize(t.name.to_s)) if t.sql.table_name.downcase != t.sql.table_name
t.attributes.each do |a|
a.sql.column_name = a.reference? ? Domgen::Naming.underscore(a.referencing_link_name.to_s) : Domgen::Naming.underscore(a.name.to_s)
end
end
end
end
FOOTER
output.close
puts IO.read(output_filename)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment