curl_scaffoldジェネレータのコード
いよいよcurl_scaffoldジェネレータのコードcurl_scaffold_generator.rbです。コードはscaffold_generator.rbをコピーして作りました。コードを順に見ていきましょう。
manifestメソッド
curl_scaffoldでは通常のscaffoldに比べ生成するファイルを減らしたので、manifestメソッドはだいぶシンプルになっています。
ファイル名の衝突チェック、ディレクトリ作成に次いで行われる、テンプレートからのアプリケーションファイル作成はview_start.html.erbとコントローラのみです。後は初期化ファイルsetup_json.rb、ライセンスファイルのコピーを行っています。
最後にconfig/route.rbの作成とモデルの作成を行います。
class CurlScaffoldGenerator < Rails::Generator::NamedBase
・・・scaffold_generator.rbと同じ ・・・
def def initialize(runtime_args, runtime_options = {})
・・・scaffold_generator.rbと同じ ・・・
end
def manifest
record do |m|
# Check for class naming collisions.
m.class_collisions"#{controller_class_name}Controller"
m.class_collisions class_name
# Controller, helper, views, test and stylesheets directories.
m.directory File.join('app/models', class_path)
m.directory File.join('app/controllers', controller_class_path)
m.directory File.join('app/views', controller_class_path, controller_file_name)
m.directory File.join('test/unit', class_path)
m.template "view_start.html.erb",
File.join('app/views', controller_class_path, controller_file_name, "start.html.erb")
m.template 'controller.rb',
File.join('app/controllers', controller_class_path, "#{controller_file_name}_controller.rb")
m.file 'setup_json.rb', 'config/initializers/setup_json.rb'
m.file 'curl-access.txt', 'public/curl-access.txt'
m.file 'curl-license-5.dat', 'public/curl-license-5.dat'
m.route_resource ":#{controller_file_name}, :collection => { :start => :get }"
m.dependency 'model', [name] + @args, :collision => :skip
end
Curl用属性クラスの作成
コマンドで指定されたテーブルのカラム情報を保持する属性(GeneratedAttribute)クラスですが、型やデフォルト値の情報はRuby on Rails用なのでCurl用の型やデフォルト値を戻してくれるGeneratedCurlAttributeクラスを定義しました。またview_start.html.erbテンプレートの処理で属性配列の最後が分かると便利なので、最終要素を表すlast属性も追加しました。
class CurlScaffoldGenerator < Rails::Generator::NamedBase
・・・省略・・・
protected
def attributes
unless (@attributes)
@attributes = @args.collect do |attribute|
GeneratedCurlAttribute.new(*attribute.split(":"))
end
@attributes[-1].last = true
end
@attributes
end
end
class GeneratedCurlAttribute
attr_accessor :name, :type, :column, :last
def initialize(name, type)
@name, @type = name, type.to_sym
@column = ActiveRecord::ConnectionAdapters::Column.new(name, nil, @type)
@last = false
end
def curl_type
@curl_type ||= case type
when :integer then "int"
when :string then "String"
else
raise "Not supported type in curl_scaffold."
end
end
def default
@default ||= case type
when :integer then 0
when :string then ""
else
raise "Not supported type in curl_scaffold."
end
end
end
config/route.rb設定メソッドの作成
config/route.rbに書かれるルーティング情報の追加メソッドroute_resourcesですが、Scaffold用に作られたものは:collection => { :start => :get }等の情報を付加できないので、やはり専用のメソッドroute_resourceに置き換えています。
module Rails
module Generator
module Commands
class Create < Base
def route_resource(resource)
sentinel = 'ActionController::Routing::Routes.draw do |map|'
logger.route "map.resources #{resource}"
unless options[:pretend]
gsub_file 'config/routes.rb', /(#{Regexp.escape(sentinel)})/mi do |match|
"#{match}\n map.resources #{resource}\n"
end
end
end
end
end
end
end
まとめ
今回のようにRuby on Railsに独自のコードジェネレータを作る事で、サーバ側のRuby on Railsのプログラムだけではなく、Curlコードの作成も飛躍的な生産性の向上がはかれる事を感じていただけたら幸いです。


