pockestrap

Programmer's memo

もっと便利に rails g migration する

前置き

Railsには、DBのマイグレーションファイルを作成する為のジェネレータ、rails g migrationがあります。 例えば、usersテーブルにemailカラムを追加したい場合、このジェネレータは以下のように使います。

$ bin/rails g migration AddEmailToUsers email:string
      invoke  active_record
      create    db/migrate/20160501030424_add_email_to_users.rb

そうすると、db/migrate/20160501030424_add_email_to_users.rbが生成されます

class AddEmailToUsers < ActiveRecord::Migration
  def change
    add_column :users, :email, :string
  end
end

問題点

私は、このコマンドにいくつかの問題があると思います。

  • カラム名を2回書かなければいけない
  • クラス名のルールを覚えなければいけない

以下で詳しく説明します。

カラム名を2回書かなければいけない

AddEmailToUsersemail:string の2箇所にemailと書かなければいけません。 同じことを2箇所に書かなければいけないのはイケてないですね。

クラス名のルールを覚えなければいけない

rails g migrationは、クラス名をパースしてどのようなマイグレーションファイルを生成するか決定します。
そのため、どのようなクラス名をつけたらどのようなファイルが生成されるかを覚えなければいけません。

また、「クラス名からアクションが決定される」というのは直感的でないと私は考えます。
「アクションを記述するとクラス名が決定される」というアプローチの方が、より自然ではないでしょうか?

解決策

以上のような問題を感じたため、rails g migrationの代替となるgem、miを作成しました。

インストール

Gemfile に以下のように追記して、bundle installするだけです。

gem 'mi'

使い方

このGemをインストールするとmiというジェネレータが追加されます。
先ほどと同じようにusersテーブルにemailカラムを追加したい場合は、以下のようなコマンドを実行します。

$ bin/rails g mi users +email:string
      create  db/migrate/20160429062420_add_email_to_users.rb

すると、db/migrate/20160429062420_add_email_to_users.rbが以下のように生成されます。

class AddEmailToUsers < ActiveRecord::Migration
  def change
    add_column :users, :email, :string
  end
end

生成されたファイルの中身は従来のrails g migrationと同一ですが、カラムの指定方法などが異なります。

miでは、「テーブル名」と「カラム名(と型)」を指定してマイグレーションファイルを生成します。
従来のジェネレータとは違いクラス名を指定する必要はなく、自動生成されます。

解説

$ bin/rails g mi users +email:string

上記のコマンドを詳しく解説していきましょう。

まず、usersはテーブル名を表します。

+email:stringは、+, email, stringの要素に分けられます。

+は、add_columnを表します。ここを-%に変えると、それぞれremove_columnchange_columnを表します。

$ bin/rails g mi users -email        # => remove_column :users, :email
$ bin/rails g mi users %email:text   # => change_column :users, :email, :text

email, stringはそれぞれカラム名と型名を表します。
remove_columnの例からわかるように、型名は省略可能です。

また、以下のようにしてオプションを渡すことが可能です。

$ bin/rails g mi users +email:string:{null:false}    # => change_column :users, :email, :string, null: false

TODOs

現在、まだまだ 実装されている機能は多くありません。

  • create_talbe ができない
  • rename_table, change_column_null などに対応していない
  • Rails 5に対応していない

以上の様なTODOが残っています。が、早いうちに実装しようと思っています!

ちなみに、Rails 5でmigrationファイルの形が変わるっぽいですね。

Rails 5から導入されたmigration versioingについて | 日々雑記

まとめ

カラムの追加など、よくあるマイグレーションファイルの生成を簡単かつ直感的なシンタックスで行えるGem、miの紹介でした。
まだ全てのマイグレーションを置き換えることは出来ませんが、確実にマイグレーションファイルの生成を効率化することが出来ると思います。

rails g migrationにフラストレーションを感じたことのある方は是非一度お試しください!