lib/arxutils/migrate.rb in arxutils-0.1.36 vs lib/arxutils/migrate.rb in arxutils-0.1.37

- old
+ new

@@ -4,120 +4,165 @@ require 'fileutils' require 'active_support' require 'active_record' require 'pp' +# ActiveRecord用ユーティリティモジュール module Arxutils + ## + # migrateに必要なファイルをテンプレートから作成し、migarteを実行する class Migrate - attr_accessor :dbinit , :dbconfig_dest_path , :dbconfig_dest_fname , :dbconfig_src_path , :dbconfig_src_fname - - def Migrate.migrate( data_ary , relation_def_fpath , module_name, count_classname_downcase , dbconfig , forced ) - src_config_dir = Arxutils.configdir - mig = Migrate.new( Dbutil::MIGRATE_DIR , src_config_dir , dbconfig, Dbutil::DATABASELOG, forced ) - # dbconfigのテンプレートは内容が固定である。convertを呼び出し、Arxのインスタンスを作成するときに、適切なdata_aryの要素を与える必要がある(ただしテンプレートへの埋め込みには用いられない - mig.make_dbconfig( dbconfig ) - - data_ary.reduce(0) { |next_num , x| - mig.make( next_num , x ) - } + # migrate用スクリプトファイル名の先頭の番号の間隔 + FILENAME_COUNTER_STEP = 10 - content_array = data_ary.map { |x| + # migrateに必要なファイルをテンプレートから作成し、migarteを実行する + def self.migrate( db_dir , src_config_dir , log_fname, migrate_dir, env, db_scheme_ary , dbconfig , opts ) + log_file_name = sprintf("%s-%s" , dbconfig.to_s , log_fname ) + mig = Migratex.new( db_dir , migrate_dir , src_config_dir , dbconfig, env, log_file_name, opts ) + # DB構成情報の生成 + # dbconfigのテンプレートは内容が固定である。 + if( opts["makeconfig"] ) + mig.make_dbconfig( opts ) + return + end + # スキーマ設定配列から、migrate用のスクリプトを作成する + db_scheme_ary.map{ |x| mig.make_script_group(x) }.flatten(1).each_with_index{|data , index| + idy = (index + 1) * FILENAME_COUNTER_STEP + mig.output_script( idy , *data ) + } + # スキーマ設定配列から、relationのmigrate用のスクリプトの内容(ハッシュ形式)の配列を作成する + content_array = db_scheme_ary.map { |x| mig.make_relation( x , "count" ) }.select{ |x| x.size > 0 } - need_count_class_plural = content_array.reduce([]){ |s,x| - s << x[:need_count_class_plural] if x[:need_count_class_plural] != nil - s - } - if content_array.size > 0 + # 複数形のクラス名を集める + need_count_class_plural = content_array.select{ |x| x[:need_count_class_plural] != nil }.map{ |x| x[:need_count_class_plural] } + + # relationのmigrateが必要であれば、それをテンプレートファイルから作成して、スクリプトの内容として追加する + if content_array.find{|x| x != nil} data_count = {count_classname: "Count" , need_count_class_plural: need_count_class_plural, } ary = content_array.collect{|x| x[:content] }.flatten count_content = mig.convert_count_class_relation( data_count , "relation_count.tmpl" ) ary.unshift( count_content ) content_array = ary end - File.open( relation_def_fpath , 'w' , {:encoding => Encoding::UTF_8}){ |f| - f.puts("module #{module_name}") - content_array.map{ |content| - f.puts( content ) - f.puts( "\n" ) - } - f.puts("end") - } - - Dbutil::DbMgr.setup( mig.dbinit ) + # relationのスクリプトを作成 + mig.output_relation_script( content_array , opts[:relation] ) + # データベース接続とログ設定 + ::Arxutils::Dbutil::DbMgr.setup( mig.dbinit ) + + # migrateを実行する mig.migrate end - - def initialize( migrate_base_dir , config_dir , dbconfig, log_fname, forced = false ) - @dbinit = Dbutil::Dbinit.new( migrate_base_dir , config_dir , dbconfig, log_fname, forced ) - @dbconfig_dest_path = @dbinit.dbconfig_dest_path - @dbconfig_src_path = @dbinit.dbconfig_src_path - @dbconfig_src_fname = @dbinit.dbconfig_src_fname - @migrate_dir = @dbinit.migrate_dir - @src_path = Arxutils.templatedir - @src_config_path = Arxutils.configdir - end + # migrate用のスクリプトの内容をテンプレートから作成し、ファイルに出力し、migrateを実行する + class Migratex + # DB接続までの初期化を行うDbinitクラスのインスタンス + attr_reader :dbinit - def convert_count_class_relation( data , src_fname ) - convert( data , @src_path , src_fname ) - end + # migrate用のスクリプトの生成、migrateの実行を行うmigratexの生成 + def initialize( db_dir , migrate_base_dir , src_config_dir , dbconfig, env, log_fname, opts ) + # DB接続までの初期化を行うDbinitクラスのインスタンス + @dbinit = Dbutil::Dbinit.new( db_dir , migrate_base_dir , src_config_dir , dbconfig, env, log_fname, opts ) + # 生成するDB構成情報ファイルパス + @dbconfig_dest_path = @dbinit.dbconfig_dest_path + # 参照用DB構成情報ファイル名 + @dbconfig_src_fname = @dbinit.dbconfig_src_fname - def convert( data , src_dir , src_fname ) - arx = Arx.new( data , File.join( src_dir, src_fname ) ) - arx.create - end - - def make_dbconfig( data ) - content = convert( data , @src_config_path , @dbconfig_src_fname ) - File.open( @dbconfig_dest_path , 'w' , {:encoding => Encoding::UTF_8}){ |f| - f.puts( content ) - } - end + # migrate用スクリプトの出力先ディレクトリ名 + @migrate_dir = @dbinit.migrate_dir + # テンプレートファイル格納ディレクトリ名 + @src_path = Arxutils.templatedir + # 構成ファイル格納ディレクトリ + @src_config_path = Arxutils.configdir + end - def make_relation( data , count_classname_downcase ) - if data[:classname_downcase] != count_classname_downcase - data[:flist].reduce( { content: [], need_count_class: nil } ){ |s, x| - case x - when "base" , "noitem" - name_base = "relation" - data[:relation] = [] unless data[:relation] - else - data[:count_classname_downcase] = count_classname_downcase - name_base = "relation_#{x}" - s[:need_count_class_plural] ||= data[:plural] - end - content = convert( data , @src_path , "#{name_base}.tmpl" ) - s[:content] << content - s + # Countクラス用のrelationのスクリプトの内容に変換 + def convert_count_class_relation( data , src_fname ) + convert( data , @src_path , src_fname ) + end + + # テンプレートファイルからスクリプトの内容に変換 + def convert( data , src_dir , src_fname ) + arx = Arx.new( data , File.join( src_dir, src_fname ) ) + # 指定テンプレートファイルからスクリプトの内容に作成 + arx.create + end + + # データベース構成ファイルをテンプレートから生成する + def make_dbconfig( data ) + content = convert( data , @src_config_path , @dbconfig_src_fname ) + File.open( @dbconfig_dest_path , 'w' , {:encoding => Encoding::UTF_8}){ |f| + f.puts( content ) } - else - {} end - end - - def make( next_num , data ) - data[:flist].reduce(next_num) do |idy , x| - idy += 10 - content = convert( data , @src_path , "#{x}.tmpl" ) - case x - when "base" , "noitem" - additional = "" + + # 英子文字で表現したクラス名が、countを表していなければ、relationを + # 英子文字で表現したクラス名が、countを表していれが、空のハッシュを返す + # スキーマでbase, noitem以外のフィールドが指定されていれば、そのフィールドに対するrelationの設定の内容を返す + def make_relation( data , count_classname_downcase ) + if data[:classname_downcase] != count_classname_downcase + # 指定フィールドのフィールド名に対応したテンプレートファイルを用いて、relation設定を作成 + data[:flist].reduce( { content: [], need_count_class: nil } ){ |s, field_name| + case field_name + when "base" , "noitem" + name_base = "relation" + # data[:relation]がnilに設定されていたら改めて空の配列を設定 + data[:relation] = [] unless data[:relation] + else + data[:count_classname_downcase] = count_classname_downcase + name_base = "relation_#{field_name}" + s[:need_count_class_plural] ||= data[:plural] + end + # テンプレートファイルからスクリプトの内容を作成 + content = convert( data , @src_path , "#{name_base}.tmpl" ) + s[:content] << content + s + } else - additional = x + {} end - fname = File.join( @migrate_dir , sprintf("%03d_create_%s%s.rb" , idy , additional , data[:classname_downcase]) ) - File.open( fname , 'w' , {:encoding => Encoding::UTF_8}){ |f| - f.puts( content ) + end + + # スキーマ設定からmigarte用スクリプトの内容を生成 + def make_script_group( data ) + data[:flist].map{ |kind| [kind, convert( data , @src_path , "#{kind}.tmpl" ), data[:classname_downcase]]} + end + + # migrationのスクリプトをファイル出力する + def output_script( idy, kind , content , classname_downcase ) + case kind + when "base" , "noitem" + additional = "" + else + additional = kind + end + fname = File.join( @migrate_dir , sprintf("%03d_create_%s%s.rb" , idy , additional , classname_downcase) ) + File.open( fname , 'w' , {:encoding => Encoding::UTF_8}){ |f| + f.puts( content ) + } + end + + # relationのスクリプトをファイル出力する + def output_relation_script( content_array , opts ) + dir = opts[:dir] + fname = opts[:filename] + fpath = File.join( dir , fname ) + File.open( fpath , "w" ){ |file| + opts[:module].map{|mod| file.puts("module #{mod}")} + content_array.map{|x| + file.puts x + file.puts "" + } + opts[:module].map{|mod| file.puts("end")} } - idy end - end - def migrate - ActiveRecord::Migrator.migrate(@migrate_dir , ENV["VERSION"] ? ENV["VERSION"].to_i : nil ) + # migrateを実行する + def migrate + ActiveRecord::Migrator.migrate(@migrate_dir , ENV["VERSION"] ? ENV["VERSION"].to_i : nil ) + end end end end