いまさら聞けないRailsのカスタムgeneratorの作成方法

はじめに

Railsのアプリケーションを作成していると、同じようなモデル(STIを使っているとよくありますよね)、同じようなコントローラ(RESTfulにすればするほど、コントローラは似てきますよね)が増えてきます。新しいモデルやコントローラを作るときに、コピー&ペーストしたあと、エディタでクラス名を置換し始めたら、カスタムgeneratorを作成するチャンスです。
カスタムgeneratorはめっちゃ簡単に作成できます。しかも、特定のアプリケーションの開発ノウハウ(アクションの作り方やRSpecの記述内容)を動作するプログラムとして記述することができます。
というわけで、カスタムgeneratorの作成方法を説明します...とおもいきや、Rails Guide (http://guides.rubyonrails.org/generators.html) に詳細な説明がありますので、細かい話はおいといて私の興味があるところだけを説明します。

generatorでできること

まずはgeneratorでできることを挙げます。(最後の失言は別として)あなたがほしいものとマッチしたならば、ぜひ、generatorを作成してみてください。

  • テンプレートから適切な名前のファイルを生成して適切なディレクトリに配置できます。
  • Railsのgeneratorで生成されるファイルの一部だけを修正して特定のアプリケーション向けのものにできます。
  • gitのコマンドを簡単に実行できます。
  • アプリケーション自体(rails new AppName -m )のテンプレートを作成できます。
  • (結局Rubyスクリプトなので、なんでもできるんじゃい!!)

最初にやること

generatorの名前を決めたら、Rails.rootディレクトリで次のコマンドを実行します。あとはどんどん記述するだけです。

$ rails generate generator <名前>

Railsのgeneratorはどこにあるの?

せっかくgeneratorを作成するのですから、よりよいコードを書きたいものですね。そのときに参考になるコードといえば、Railsに含まれているgeneratorです。ここにはノウハウがたっぷりつまっています。
Railsのgeneratorは、/path/to/gems/railties-/lib/rails/generators/rails/ にあります。RVMを使っている場合は ~/.rvm/gems//gems/railties-/lib/rails/generators/rails/ です。
scaffoldのgeneratorなんかはいいですね。hook_forをうまく使って、DRYになってます。参考にしたいものです。

require 'rails/generators/rails/resource/resource_generator'

module Rails
  module Generators
    class ScaffoldGenerator < ResourceGenerator #metagenerator
      remove_hook_for :resource_controller
      remove_class_option :actions

      hook_for :scaffold_controller, :required => true
      hook_for :stylesheets
    end
  end
end

テンプレートはどこにどうやって記述するの?

Rails Guide (http://guides.rubyonrails.org/generators.html#lib) には、lib以下やlib/tasks以下に特定の文字列に含む特定のRubyスクリプトを配置するメソッドの説明があります。

lib("special.rb", 'p Rails.root')
rakefile("test.rake", 'hello there')

でも、本当に知りたいのは lib/generators/<名前>/template.rb から lib/<アプリケーションの名前空間:name_space>/foo.rb を生成するやり方ですよね。
まずは、「lib//foo.rb」、つまり、ディレクトリを作成してから適切な名前のファイルを配置する方法です。以下のようにlibメソッドの第1引数にディレクトリを追加して、適切なところに「#{file_name}」を記述するだけです。ちょろいですね。

lib("name_space/#{file_name}.rb", 'p Rails.root')

次にerbのテンプレートファイルからRubyスクリプトを生成する方法です。それには Thor の template メソッド (http://rdoc.info/github/wycats/thor/master/Thor/Actions#template-instance_method) を使います。

dest = "lib/name_space/#{file_name}"
log :lib, dest
template("template.rb", dest)

おわりに

まだまだ説明したいことがありますが、ここらあたりで今日は失礼しますw

--- 参考情報

--- PR広告
記事を読んでくださり、ありがとうございます。もしよろしければ、この記事の著者が提供している無料のサービス「かくってる?」をお試しください。