Symfony 1.4のschema.ymlからRuby on Railsのmodelを生成する


昔からあるプロジェクトを移行しようと思ったときに、とりあえず移行先のプロジェクト
でDBにアクセスして、挙動を確認したり、バッチ処理など、影響の小さい部分から
移行作業を進めたいということがあると思います。
今回はsymfony 1.4のプロジェクトのDBの定義(schema.yml)からRuby on Railsのmodelを作成
してみます。

Ruby on Railsのmodel Generatorコマンドの確認

Ruby on RailsにはmodelのGeneratorコマンドでmodelを作成することが出来ます。
何もオプションを加えずにgenerateコマンドを実行した場合にはmigrationファイル
まで作成されてしまいますが、

$ bin/rails generate model product
      invoke  active_record
      create    db/migrate/20170724105123_create_products.rb
      create    app/models/product.rb
      invoke    test_unit
      create      test/models/product_test.rb
      create      test/fixtures/products.yml

model generator コマンドで引数を指定せずにusageを表示してみると
--no-migrationを加えることで、migrationファイルを作成せずに
modelファイルを作成できることがわかります。

$ bin/rails generate model
Usage:
  rails generate model NAME [field[:type][:index] field[:type][:index]] [options]

Options:
      [--skip-namespace], [--no-skip-namespace]  # Skip namespace (affects only isolated applications)
      [--force-plural], [--no-force-plural]      # Forces the use of the given model name
  -o, --orm=NAME                                 # ORM to be invoked
                                                 # Default: active_record

ActiveRecord options:
      [--migration], [--no-migration]        # Indicates when to generate migration
                                             # Default: true
...

--no-migrationを指定して実行すると、migrationファイルを作成せずに
modelのみが作られることが確認できます。

$ bin/rails generate model product --no-migration
      invoke  active_record
      create    app/models/product.rb
      invoke    test_unit
      create      test/models/product_test.rb
      create      test/fixtures/products.yml

RakeタスクからのGeneratorコマンドの実行

--no-migrationのオプションをつけてgenerate modelをすれば、modelが
作成されることは分かりましたが、modelが多い場合はコマンドを手作業で
実行するのも大変になります。
そのためにSymfonyのschema.ymlを読み取って、rakeで一括でgenerate modelを
する仕組みを作ります。
以下のようにrakeからRails::Generators.invokeを使うことで
generate modelと同じ処理をすることが出来ます。

Rails::Generators.invoke 'active_record:model', ["product", "--no-migration" ]

例えば、symfonyのチュートリアルサイト 3日目: データモデル - - Symfonyにある
schema.ymlをプロジェクトのrootディレクトリに設置して、読み込む場合の処理は
以下のようになります。

symfony.rake
namespace :symfony do
  desc "generate model from symfony 1.4 schema.yml"
  task :import_schema => [:environment] do
    schema = YAML.load_file(Rails.root.join('schema.yml'))
    models = schema.keys
    # generate model
    models.each do |el|
      Rails::Generators.invoke 'active_record:model', [el.tableize.singularize, "--no-migration" ]
    end
  end
end

schema.ymlとgenerate modelのコマンドの表現を合わせるためにtableizeや
singularizeメソッドを使って、適切な文字にします。

bin/rake symfony:import_schema

あとは上記のコマンドを実行すれば、modelを作成することが出来ます。