研究用に書いていた::Migs.describeがRSpecのdescribeと競合してしまって困ったので、
module ::Migs spec do describe ::Job do # テストコード end end end
と書ける様にMigs.specを書いた時にはまった点をメモ
Migs.specの実装は以下のようにしました
module ::Migs class << self # solve duplicated describe method def spec swap_method :orig_describe, :describe yield swap_method :describe, :orig_describe end private def swap_method(dest, orig) @@dest, @@orig = dest, orig class << self alias_method @@dest, @@orig remove_method @@orig end end end end
ところが、これで最初は動いていたのですが、本体のコードをリファクタリングしている途中でModule#remove_methodでdescribeが無いと怒られてしまいました。しばらくテストコードの方を眺めて悩んでいたのですが、冷静に考えると変更したのは本体なんだからそっちにヒントがあるだろうということで、本体を見てみると、
module ::Migs module ModuleMethods def describe # ... end # ... end extend ModuleMethods end
と書いていました。気づいた方がいらっしゃると思いますが、書き換える前はextendする代わりにclass << selfで書いていました。Module#remove_methodは呼び出したモジュール内のメソッドを削除するので、この場合はMigs::ModuleMethods内でModule#remove_methodを呼ばなければいけなかったのです。
という訳で書き直したswap_methodメソッドは以下、
def swap_method(dest, orig) ModuleMethods.module_eval do alias_method dest, orig remove_method orig end end
これで、無事にテストに通りました。(module_eval使わなくていい方法無いかな)
まとめ
Module#remove_methodは呼び出したモジュール内のメソッドしか削除しない。