概要
Thor を利用した CLI Application を DRY にするちょっとやり過ぎな enel gem を作成した
enel gem 利用前
Thor を利用した CLI アプリケーション を作成するとき、各コマンドの呼び出しは似たようなものになりがち。
Thor を継承したクラスのロジックはできるだけ薄くする。
テスタビリティ向上のため。
すると、似たようなクラスの呼び出しロジックばかりが残る。
何度も書きたくない。
DRY にしたい。
hoge.rb
require 'thor'
class Hoge < Thor
desc 'hoge1', 'hoge1'
def hoge1
Hoge::Commands::Hoge1.new.run
end
desc 'hoge2', 'hoge2'
def hoge2(args1)
Hoge::Commands::Hoge2.new.run(args1)
end
desc 'hoge3', 'hoge3'
def hoge3(args1, *options)
Hoge::Commands::Hoge3.new.run(args1, *options)
end
# hoge4, hoge5... more!
end
Hoge.start(ARGV)
./commands/hoges.rb
module Hoge::Commands
class Hoge1
def run
end
end
end
enel gem 利用後
こう書けるようにします。
※ Thor の仕組み上、メソッドの宣言は省略できない。
この部分に関しては別途別のコードジェネレータを作るのが良いかな、と思っている
hoge.rb
require 'thor'
require 'active_support/inflector'
require 'enel'
require_relative 'commands/hoges'
class Hoge < ::Thor
extend Enel
desc 'hoge1', 'hoge1'
def hoge1
end
desc 'hoge2', 'hoge2'
def hoge2(args1)
end
desc 'hoge3', 'hoge3'
def hoge3(args1, *options)
end
# hoge4, hoge5... more!
# ここに自分で考えた Command 呼び出し規約に基づいたロジックを記述する
define_call_command(proc { |*args|
command = args.first.to_s.camelize
params = args[1..-1]
puts Object.const_get("Commands::#{command}").new.run(*params)
})
end
Hoge.start(ARGV)
./commands/hoges.rb
module Hoge::Commands
class Hoge1
def run
end
end
end
- 実行結果
$ ruby hoge.rb hoge1
hoge1
$ ruby hoge.rb hoge2 a
a
$ ruby hoge.rb hoge3 a b c
a
b
c