My goal is to replace methods in the String
class with other methods that do additional work (this is for a research project). This works for many methods by writing code in the String
class similar to
alias_method :center_OLD, :center
def center(args*)
r = self.send(*([:center_OLD] + args))
#do some work here
#return something
end
For some methods, I need to handle a Proc as well, which is no problem. However, for the scan
method, invoking it has the side effect of setting special global variables from the regular expression match. As documented, these variables are local to the thread and the method.
Unfortunately, some Rails code makes calls to scan
which makes use of the $&
variable. That variable gets set inside my version of the scan
method, but because it's local, it doesn't make it back to the original caller which uses the variable.
Does anyone know a way to work around this? Please let me know if the problem needs clarification.
If it helps at all, all the uses I've seen so far of the $&
variable are inside a Proc passed to the scan
function, so I can get the binding for that Proc. However, the user doesn't seem to be able to change $&
at all, so I don't know how that will help much.
Current Code
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
Of course I'll do more things before returning r
, but this even is problematic -- so for simplicity we'll stick with this. As a test case, consider:
"hello world".scan(/l./) { |x| puts x }
This works fine both with and without my version of scan
. With the "vanilla" String
class this produces the same thing as
"hello world".scan(/l./) { puts $&; }
Namely, it prints "ll" and "ld" and returns "hello world". With the modified string class it prints two blank lines (since $&
was nil
) and then returns "hello world". I'll be happy if we can get that working!