Created
September 30, 2013 06:28
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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