Redefining Kernel Methods on the Fly

(Gavin Kistner) #1

As part of my Quest to find a clean way to get #puts and #print to 'work' in ERB, I was experimenting with ways I thought I could redefine Kernel methods from within a method. Why don't test1 and test2 work in the following code?

module Kernel
         alias_method :_puts, :puts
         def puts(s); _puts "HIDDEN"; end
end
puts "1: I DON'T WANNA SEE THIS"
module Kernel
         undef_method :puts
         alias_method :puts, :_puts
end
puts "1: OK to see this"

def run_test1
         Kernel.instance_eval{
                 alias_method :_puts, :puts
                 def puts(s); _puts "HIDDEN"; end
         }
         puts "2: I DON'T WANNA SEE THIS"
         Kernel.instance_eval{
                 undef_method :puts
                 alias_method :puts, :_puts
         }
         puts "2: OK to see this"
end
run_test1

def run_test2
         kb = Kernel.instance_eval{ binding }
         eval( "alias_method :_puts, :puts", kb )
         eval( 'def puts(s); _puts "HIDDEN"; end', kb )
         puts "3: I DON'T WANNA SEE THIS"
         eval( "undef_method :puts", kb )
         eval( "alias_method :puts, :_puts", kb )
         puts "3: OK to see this"
end
run_test2

[[Slim:~/Desktop] gavinkis% ruby -vW0 binding_test.rb
ruby 1.8.2 (2004-12-25) [powerpc-darwin8.0.0]
HIDDEN
1: OK to see this
2: I DON'T WANNA SEE THIS
2: OK to see this
HIDDEN

(Nakada, Nobuyoshi) #2

Hi,

At Fri, 19 Aug 2005 14:50:38 +0900,
Gavin Kistner wrote in [ruby-talk:152854]:

def run_test1
         Kernel.instance_eval{

Use module_eval instead of instance_eval.

···

--
Nobu Nakada

(Gavin Kistner) #3

Er, yup, that did the trick! :slight_smile: Silly I didn't think of it.

Any idea why the last item (using eval with the binding of Kernel) manages to change the puts, but cannot change it back?

···

On Aug 19, 2005, at 12:24 AM, nobuyoshi nakada wrote:

At Fri, 19 Aug 2005 14:50:38 +0900,
Gavin Kistner wrote in [ruby-talk:152854]:

def run_test1
         Kernel.instance_eval{

Use module_eval instead of instance_eval.