LoginSignup
2
2

More than 5 years have passed since last update.

ฅ(・ω・ฅ){ Thor を利用した CLI Application を DRY にするちょっとやり過ぎな enel gem } #ruby #thor

Posted at

:zap: 概要

Thor を利用した CLI Application を DRY にするちょっとやり過ぎな enel gem を作成した

:baby_chick: 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

:chicken: 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

:books: 外部資料

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2