予習 Rails3 (2) Thor
さて、2回目の今回は Thor。北欧神話で言うと最強らしい。
http://ja.wikipedia.org/wiki/%E3%83%88%E3%83%BC%E3%83%AB
でも Rails3 で使うのはこっち。
http://github.com/wycats/thor
Ruby の Thor は平たく言えばコマンドライン操作に対して、より簡便なオプション解釈の手段を提供してくれるDSLだ。個人的には Sake に似ているなーという印象。オプション解釈と聞いて GNU の getopt とか getopt_long といったライブラリが思い浮かぶ人もいるかもしれないが、Thor ができるのはもうちょっと広範囲に及ぶ。
Thor はgemで簡単にインストールできる。
$ sudo gem install thor
渡せるオプションは以下の形式。
:boolean - is parsed as --option or --option=true :string - is parsed as --option=VALUE :numeric - is parsed as --option=N :array - is parsed as --option=one two three :hash - is parsed as --option=name:string age:integer
では実際に例を。マニュアルから引用。使い方としては Thor クラスを継承することに始まる。
class App < Thor # [1] map "-L" => :list # [2] desc "install APP_NAME", "install one of the available apps" # [3] method_options :force => :boolean, :alias => :string # [4] def install(name) user_alias = options[:alias] if options.force? # do something end # other code end desc "list [SEARCH]", "list all of the available apps, limited by SEARCH" def list(search="") # list everything end end
このスクリプトを app.thor として保存し、同一ディレクトリで
$ thor list
もしくは
$ thor -T
とすると
$ thor -T app --- /usr/local/ruby_1_9_2/bin/thor app:install APP_NAME # install one of the available apps /usr/local/ruby_1_9_2/bin/thor app:list [SEARCH] # list all of the available apps, limited by SEARCH
このようにタスクと、そのデスクリプションが表示される。なお上記のソースでは install、list、force、aliasの4つのオプションを定義している。そのため、
$ thor app:install test --force --alias=useralias
もしくは
$ thor app:list search_string
といった指定が可能になる。なお、システム全体でタスクを共有したい場合
# thor install app.thor
とすることで app.thor をどのディレクトリにいても利用できるようになる。なお、タスクのインストールはリモートURLからも可能だ。一度インストールした後にタスクに変更を加えた場合は、
# thor update app.thor
などとしてシステムにインストールされたタスクのアップデートを行う。
ところで、Thor には Thor::Group というクラスがあり、定義されたメソッドすべてを一度に実行可能だ。
class Counter < Thor::Group desc "Prints 1, 2, 3" def one puts 1 end def two puts 2 end def three puts 3 end end
これを counter.thor として保存してある場合、
$ thor counter
としてクラス名のみをthorコマンドに渡すことで結果「1 2 3」を得られる。
あと、Thor のマニュアルの最後には簡単なジェネレーターのサンプルがあるんだけど、Rails3 のジェネレータを理解するのに役立つだろう。
class Newgem < Thor::Group include Thor::Actions # Define arguments and options argument :name class_option :test_framework, :default => :test_unit def self.source_root File.dirname(__FILE__) end def create_lib_file template('templates/newgem.tt', "#{name}/lib/#{name}.rb") end def create_test_file test = options[:test_framework] == "rspec" ? :spec : :test create_file "#{name}/#{test}/#{name}_#{test}.rb" end def copy_licence if yes?("Use MIT license?") # Make a copy of the MITLICENSE file at the source root copy_file "MITLICENSE", "#{name}/MITLICENSE" else say "Shame on you…", :red end end end
このようにかなりよくできているモジュールなので、Rails を使う以外に簡単なコマンドラインアプリケーションやバッチ処理などでも Thor を使うことでその開発がぐっと楽になるハズ。なお、ここで紹介した以外にももっとたくさんの機能があるのでドキュメントを見てほしい。