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

 
              
               
                          
                           
                          
                           
                          
                           
                          
                           
                          
                           
                          
                           
                          
                           
                          
                           
                          
                           
                          
                           
                          
                           
                          
                           
                              
                               
                              
                               
                              
                               
                              
                               
                              
                               
                      
                     
                      
                     
                      
                     
                      
                     
                      
                     
                      
                     
                      
                     
															
														 
															
														.png) 
     
     
     
     
     
													 
													 
													 
													 
													 
										
									

 
                    
