String
私の目標は、クラス内のメソッドを、追加の作業を行う他のメソッドに置き換えることです (これは研究プロジェクト用です)。String
これは、次のようなクラスでコードを記述することにより、多くのメソッドで機能します。
alias_method :center_OLD, :center
def center(args*)
r = self.send(*([:center_OLD] + args))
#do some work here
#return something
end
一部のメソッドでは、Proc も処理する必要がありますが、これは問題ありません。ただし、このメソッドを呼び出すと、正規表現の一致から特別なグローバル変数scan
が設定されるという副作用があります。文書化されているように、これらの変数はスレッドとメソッドに対してローカルです。
残念ながら、いくつかの Rails コードは変数scan
を使用する呼び出しを行います。$&
その変数は私のバージョンのscan
メソッド内で設定されますが、ローカルであるため、変数を使用する元の呼び出し元には戻りません。
これを回避する方法を知っている人はいますか?問題の説明が必要な場合はお知らせください。
これが役に立ったとすれば、これまでに見た変数の使用はすべて、関数に$&
渡された Proc 内にあるscan
ため、その Proc のバインドを取得できます。ただし、ユーザーはまったく変更できないようです$&
ので、それがどのように役立つかはわかりません。
現在のコード
class String
alias_method :scan_OLD, :scan
def scan(*args, &b)
begin
sargs = [:scan_OLD] + args
if b.class == Proc
r = self.send(*sargs, &b)
else
r = self.send(*sargs)
end
r
rescue => error
puts error.backtrace.join("\n")
end
end
end
もちろんr
、 に戻る前にさらに多くのことを行いますが、これにも問題があります。簡単にするために、これに固執します。テスト ケースとして、次のことを検討してください。
"hello world".scan(/l./) { |x| puts x }
これは、私のバージョンの の有無にかかわらず正常に動作しscan
ます。「バニラ」String
クラスでは、これは次と同じものを生成します
"hello world".scan(/l./) { puts $&; }
つまり、"ll" と "ld" を出力し、"hello world" を返します。変更された文字列クラスを使用すると、2 つの空白行が出力され ( $&
was であるためnil
)、"hello world" が返されます。それが機能するようになれば幸いです。