guard-spork と guard-ego を組み合わせる場合の問題点

該当 Guard クラス(guard-spork なら Guard::Spork、guard-ego なら Guard::Ego)の検索に問題がある様です。

  • guard 0.3.10
  • guard-spork 0.1.4
  • guard-ego 0.0.1

guard-ego を利用する事で、Guardfile を変更した際に Guard が再起動される様になります。
その際に、guard-spork も利用していた場合、以下の様なエラーメッセージが出力されて例外終了します。

Guard is now restarting...
ERROR: Invalid Guardfile, original error is:
wrong number of arguments (2 for 1)
ERROR: Guard::Ego guard failed to achieve its <run_on_change> command: exit
Guard Guard::Ego has just been fired

これは、Guard.get_guard_class の処理に問題があるためと思われます。

  def get_guard_class(name)
      require "guard/#{name.downcase}"
      klasses = []
      ObjectSpace.each_object(Class) do |klass|
        klasses << klass if klass.to_s.downcase.match(/^guard::#{name.downcase}/)
      end
      klasses.first
    rescue LoadError
      UI.error "Could not find gem 'guard-#{name}', please add it in your Gemfile."
    end

何が問題かというと、guard-spork は Guard::Spork と Guard::Spork::Runner というクラスをロードします。そのため、上記のコードでは、Guard::Spork::Runner が使われてしまう可能性があるわけです(Guard::Spork::Runner が使われた場合、引数の数が異なるために例外となります)。

guard を作る際の規約は、ドキュメントの"Create a guard"の節で説明されています。以下は一部を抜粋したものです。

  • guard の名称は、
    • ファイル名 guard-.rb
    • クラス名は Guard::
  • guard のクラスは Guard::Guard クラスを継承し、特定のメソッドをオーバーライドする

これを見た感じ、ObjectSpace からクラス名の前方一致でクラスを拾い集める必要性はなく、特定のクラス名が使えるか否かで判断できるように思えます。

もしかしたら、使い方を間違えているだけかもしれませんが、恥ずかしげもなく英語でバグレポートを出してみました。

github でバグ報告をする場合、課題報告が先なのか、プルリクエストでやれるのか、よくわかりません。なので、とりあえず gist と課題報告で済ませてしまいました。

追記: 2011/02/21

pull request してマージされました。