読者です 読者をやめる 読者になる 読者になる

tech-dig

新しい技術が見つかるブログ

rails generate で使われるコマンドと用途について

Ruby on Rails Ruby

Rails には、機能を開発する上で雛形になるソースコードを自動生成するためのコマンドとして、 generate コマンドが用意されています。
非常に便利なコマンドではあるのですが、正しく使い分けないと不必要なソースコードが生成されて後から消す必要が出てきたりします。

generate でできることはたくさんありますが、ここでは主要と思われる用途に絞ってご紹介します。
(出力例では、テンプレートエンジンに slim、Javascript の記述に CoffeeScript、テストに RSpec を利用しています)

generate コマンドの基本形

基本的なコマンドのフォーマットは下記のようになっています。

Usage: rails generate GENERATOR [args] [options]

generate コマンドには g というショートカットが用意されており、下記のように実行できます。

rails g scaffold

また、dry-run などの便利なコマンドもあるので、ぜひ意識して使ってみてください。
オプションを忘れた場合は、rails g scaffold -hrails g model -h などで確認できます。

General options:
  -h, [--help]     # ヘルプを表示する
  -p, [--pretend]  # ドライランを実行する(ファイルは生成されない)
  -f, [--force]    # すでに生成予定のファイルが存在する場合に上書きする
  -s, [--skip]     # すでに生成予定のファイルが存在する場合にスキップする
  -q, [--quiet]    # 生成時のプロセスを標準出力しない

ちなみに生成予定のファイルがすでに存在するが -f-s を指定していなかった場合、下記のように対話的に確認されます。

Overwrite /path/to/file (enter "h" for help) [Ynaqdh]

generate コマンドの用途と種類

基本形についておさえたところで、generate コマンドでよく使われる scaffold, controller, model, migration の4つの用途に絞ってご紹介します。

一通りのCRUDを実現する (rails g scaffold)

Usage:
  rails generate scaffold NAME [field[:type][:index] field[:type][:index]] [options]
migration model routing controller view helper asset test

scaffold ("足場" の意)を使うと、モデル・ビュー・ルーティング・マイグレーション・コントローラーまで、テスト込みで一括でファイルを作成します。

例えば、

rails g scaffold User

を実行すると、ルーティングに resources :users が追加され、アプリケーションにおける基本的な機能である一覧(index)、詳細(show)、新規作成(new/create)、編集(edit/update)、削除(destroy) を実現するために必要なファイルが追加されます。

$ rails g scaffold User -p | grep invoke
      invoke  active_record
      invoke    rspec
      invoke  resource_route
      invoke  scaffold_controller
      invoke    slim
      invoke    rspec
      invoke      rspec
      invoke    helper
      invoke      rspec
      invoke    jbuilder
      invoke  assets
      invoke    coffee
      invoke    scss
      invoke  scss

コントローラーを追加したい (rails g controller / scaffold_controller)

コントローラーを追加する場合は、下記の2種類のコマンドがあります。

Usage:
  rails generate controller NAME [action action] [options]

Usage:
  rails generate scaffold_controller NAME [field:type field:type] [options]
COMMAND migration model routing controller view helper asset test
controller × × ×
scaffold_controller × × × ×

アセットを生成するかどうか、という違いがありますが、より大きな差としては下記のような デフォルトアクションの差 です。

  • controller: デフォルトのアクションが設定されない
  • scaffold_controller: scaffold で設定されるデフォルトアクションが設定される

Rails における一般的な RESTful コントローラーを定義したい場合は scaffold_controller を、そうでない場合は controller を使うのが良いかと思います。

$ rails generate scaffold_controller User -p | grep invoke
      invoke  slim
      invoke  rspec
      invoke    rspec
      invoke  helper
      invoke    rspec
      invoke  jbuilder

$ rails generate controller User -p | grep invoke
      invoke  slim
      invoke  rspec
      invoke  helper
      invoke    rspec
      invoke  assets
      invoke    coffee
      invoke    scss

モデルのみ追加したい (rails g model)

Usage:
  rails generate model NAME [field[:type][:index] field[:type][:index]] [options]
migration model routing controller view helper asset test
× × × × ×

モデルのみを作成するコマンドも用意されています。 開発の中でモデルのみ先に作ることもあるかと思いますが、そういった場合に使いやすいコマンドです。

$ rails generate model Article
      invoke  active_record
      create    db/migrate/20160918233116_create_articles.rb
      create    app/models/article.rb
      invoke    rspec
      create      spec/models/article_spec.rb

model コマンドでは、コマンドの中で migration ファイルの中身を指定することができます。

$ rails generate model User name:string age:integer
class CreateUsers < ActiveRecord::Migration[5.0]
  def change
    create_table :users do |t|
      t.string :name
      t.integer :age

      t.timestamps
    end
  end
end

また、下記のように reference を用いて association を指定することもできます。

$ rails generate model book asin:string title:string author:reference
class CreateBooks < ActiveRecord::Migration[5.0]
  def change
    create_table :books do |t|
      t.string :asin
      t.string :title
      t.reference :author

      t.timestamps
    end
  end
end

マイグレーションのみ追加したい (rails g migration)

Usage:
  rails generate model NAME [field[:type][:index] field[:type][:index]] [options]
migration model routing controller view helper asset test
× × × × × × ×

単純にマイグレーションファイルのみを足したい場合はこちらのコマンドで OK です。
モデルと同様に、コマンドの引数としてカラム名などを指定することができます。

$ be rails generate migration AddCategoryToBook category:string | grep invoke
      invoke  active_record
class AddCategoryToBook < ActiveRecord::Migration[5.0]
  def change
    add_column :books, :category, :string
  end
end