query: tag:generator

merbでGeneratorプラグインを作る方法を紹介します。

merbのgeneratorの仕組みは、
templater
という汎用的なGeneratorフレームワークを使って作られています。
なので、基本的にはtemplaterを使ったGeneratorの作り方という事になります。

まずは、Generatorプラグインのひな形を生成します。

pre>>
% merb-gen plugin hello
<<--

Gemの形で提供されるものであれば、merb-pluginの形式である必要は無いですが、簡単にそれを用意してくれるので、merb-gen pluginを使ってみました。

さて、続いて、GEM_ROOTにGeneratorsというファイルを作ります。

ruby>>
scope 'merb-gen' do
dir = File.join(File.dirname(FILE), 'lib', 'generators/')
Merb.add_generators dir + 'hello_generator'
end
<<--

続いて、GEM_ROOT/lib以下のディレクトリ構成を以下のような感じにします。

pre>>
lib
-- generators |-- hello_generator.rb -- templates
-- hello |-- app | -- app以下のファイル群
-- spec -- spec以下のファイル群
<<--

hello_generator.rbが、Railsのgeneratorで言うところの
Generatorマニフェストファイルに相当します。

以下はmerb-mailerのgeneratorファイルの例です。

ruby>>
module Merb::Generators
class MailerGenerator < NamespacedGenerator

def self.source_root
  File.dirname(__FILE__) / 'templates' / 'mailer'
end

desc <<-DESC
  Generates a mailer
DESC

option :testing_framework, :desc => 'Testing framework to use (one of: rspec, test_unit)'

first_argument :name, :required => true, :desc => "mailer name"

template :mailer do |t|
  t.source = 'app/mailers/%file_name%_mailer.rb'
  t.destination = File.join("app/mailers", base_path, "#{file_name}_mailer.rb")
end

template :notify_on_event do |t|
  t.source = 'app/mailers/views/%file_name%_mailer/notify_on_event.text.erb'
  t.destination = File.join("app/mailers/views", base_path, "#{file_name}_mailer/notify_on_event.text.erb")
end

template :controller_spec, :testing_framework => :rspec do |t|
  t.source = 'spec/mailers/%file_name%_mailer_spec.rb'
  t.destination = File.join("spec/mailers", base_path, "#{file_name}_mailer_spec.rb")
end

end

add :mailer, MailerGenerator
end
<<--

あとは、GemをインストールすればOK.

posted by genki genki on Thu 5 Feb 2009 at 05:39 with 0 comments

MerbのGeneratorは、merb-genというコマンドに集約されています。
Railsではscript/{generate|destroy}を使いますが、独立したコマンドになっているので、
MERB_ROOT以外の場所でも利用可能です。

さて、Merbでも、RailsのようにGeneratorを独自に作る事が出来るのですが、
そのためにはGEM_ROOTにGeneratorsというファイルを作り、
以下のように自分をGeneratorとして登録するコードを書きます。

ruby>>
scope 'merb-gen' do
dir = File.join(File.dirname(FILE), 'lib', 'generators/')
Merb.add_generators dir + 'mailer_generator'
end
<<--

MerbのGeneratorは、より汎用的なGeneratorを作る仕組みである、
templater
を使って実装されています。
そのため、Merb用のGeneratorを作る場合は、上記ファイルのscopeに
merb-genを指定する必要があります。

Railsの場合は、foo_generater のようにGem名のサフィックスでGenerator
を提供するかどうか判別していましたが、
こっちのほうがもっと賢いやり方だと思います。

posted by genki genki on Tue 13 Jan 2009 at 23:24 with 0 comments
記事の引越しから漏れていたのでサルベージ。 Generatorプラグインの作り方をメモしておきます。 まずはプラグインの雛形を作ります。 shell-unix-generic>> $ ./script/generate plugin foo <<-- 次にGeneratorプラグインに必要なディレクトリを用意。 shell-unix-generic>> $ mkdir -p vendor/plugins/foo/generators/foo/templates <<-- FooGeneratorクラスの定義ファイルを作成 **vendor/plugins/foo/generators/foo/foo_generator.rb** ruby_on_rails>> class FooGenerator < Rails::Generator::NamedBase def initialize(runtime_args, runtime_options = {}) super ~ 引数・オプションの解釈と初期化 ~ end def manifest record do |m| ~ マニフェスト ~ end end end <<-- マニフェストの書き方は [この辺](http://dev.rubyonrails.org/browser/trunk/railties/lib/rails_generator/generators/components/controller/controller_generator.rb) が参考になります。基底クラスは、Rails::Generator::Baseの派生クラスなら何でもOKです。 続いて、マニフェストから参照するテンプレートファイルをtemplatesディレクトリの中に作ります。テンプレートファイルはERbテンプレートなので、Generatorクラスのコンテクストでrhtmlを書くような感じで記述できます。 以上で完了。Generatorを使うときは以下の通り。 shell-unix-generic>> $ ./script/generate foo <<-- マニフェストの書式を以下にまとめておきます。
**`m.class_collisions( *class_names)`** 生成するクラス名の衝突を検出します。 Generatorで生成する予定のクラス名をすべて列記しておきましょう。 **`m.directory(relative_path)`** RAILS_ROOTからの相対パスで、指定したディレクトリを利用する事を 宣言します。 **`m.template(relative_source, relative_destination, template_options = {})`** Generatorが生成するファイルを宣言します。`relative_source`は、templatesディレクトリからの相対パスでERbテンプレートを指定します。`relative_destination`には生成されるファイルの場所を`RAILS_ROOT`からの相対パスで記述します。 `template_options`には、`:assigns => {:foo => some_thing}` のような感じで、ERbテンプレートから参照可能な値を設定する事ができます。 **`m.readme( *relative_sources)`** helpドキュメントを指定します。指定したファイル群は単純に連続出力されます。 **`m.migration_template(relative_source, relative_destination, template_options = {})`** migrationファイルの生成を宣言します。migrationファイルは、ファイル名の先頭に005_のようなプレフィックスが付くので、専用のメソッドが用意されています。 `relative_destination`は、migrationファイルを配置するディレクトリを、`RAILS_ROOT`からの相対パスで指定します。生成するファイル名は、`template_options[:migration_file_name]` で明示的に指定するか、さもなくばGeneratorの引数から自動的に決定されます。 そのほかの挙動はm.templateと同じです。  **`m.dependency(generator_name, args, runtime_options = {})`** Generatorの依存関係を宣言します。これによってメタジェネレータを記述する事も可能です。素晴らしいですね。 **`m.file(relative_source, relative_destination, file_options = {}) {|sf| ...}`** ファイルのコピーを宣言します。`relative_source`、`relative_destination` はそれぞれ`RAILS_ROOT`からの相対パスです。 `file_options`には、`:chmod`, `:shebang`, `:collision`を指定します。 詳細な挙動については [こちら](http://edgedocs.planetargon.org/classes/Rails/Generator/Commands/Create.html#M004122) を参照のこと。 ブロック引数は、`relative_source`で指定したファイルが何らかのテンプレートファイルであるときに、テンプレートを展開する処理を記述します。そうでない場合は省略可能です。 より詳細な情報が必要な場合は、 [Rails::Generator::Commands::Createクラスのドキュメント](http://edgedocs.planetargon.org/classes/Rails/Generator/Commands/Create.html) 及び [Createクラスの基底クラスであるRails::Generator::Commands::Baseのドキュメント](http://edgedocs.planetargon.org/classes/Rails/Generator/Commands/Base.html) をご覧ください。 **更新履歴** * 2006/08/10 マニフェストの書き方を最後の方にまとめておきました。 * 2007/11/22 記事の移行からもれていたのでサルベージ
posted by genki genki on Thu 22 Nov 2007 at 05:43 with 0 comments