これ僕.com:行動分析学マニアがおくる行動戦略

意図と行動のギャップから生じる「不自由さ」への挑戦。果たして僕たちに自由はあるのか?

script/generateの続き templateについて

Rails::Generators::Commands::Createクラスにtemplate()というメソッドがある。file()を使っているのでテンプレートファイルをコピーするのだが、その際、ERBを使ってテンプレートファイルの中身を置き換えることができるらしい。試してみた。

template_test_generator.rb
require 'rbconfig'

class TemplateTestGenerator < Rails::Generator::NamedBase
  attr_reader :hoge # (1)

  def manifest
    record do |m|
      @hoge = 'generated_attr' # (2)
      m.template 'test.rb', File.join('app/models', "#{file_name}.rb")
    end
  end

end

(1)のように属性を定義しておくことで、テンプレートファイルから参照できる。Rails::Generators::NamedBaseに定義されている属性は、全てテンプレートから参照できるようだ。(2)は実際にテンプレートファイルに埋め込む値を設定しているだけ。

テンプレートファイル templates/test.rb
class <%= class_name %> # (3)クラス名を埋め込む
  attr_reader :<%= hoge %> # (4)自分で好きな値を埋め込む
end

(3)はRails::Generators::NamedBaseに定義されているclass_nameを使用している。class_nameには、実行時に指定された値がクラス名の形に変換されて格納されているので、テンプレートファイルから参照することで、class〜部分のコードが完成する。
また(1)のように自作Generatorに属性を定義しておけば、(4)のようにすることで、自分で任意の値をテンプレートファイルに埋め込むことができる。

実行結果
$ ruby script/generate template_test foo bar
       create  app/models/foo.rb
作成されたファイル foo.rb
class Foo
  attr_reader :generated_attr
end