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コードの作成も飛躍的な生産性の向上がはかれる事を感じていただけたら幸いです。