Difference between define_method and def method; end

ruby

    Sponsored Links

    Next

  • 1. Ruby and gcc 2.95.4
    Hi, Has anyone tried current Ruby with gcc 2.95.4? Is it known to work? I get fantastic memory leaks with it... Can anybody confirm this? Thanks. Michael

Difference between define_method and def method; end

Postby Rune Hammersland » Wed, 01 Nov 2006 20:37:17 GMT

Hello dear Rubyists.

It was suggested on the IRC channel that I try the ML for this  
problem ...

While looking at how to undefine a method, I found out that there is  
a difference in how define_method and the def ... end block works.  
Example coming up:

# Two classes to play with.
class Parent
     def lol
         puts "P: LOL"
     end
end

class Child < Parent
     # Commenting out the redefinition doesn't help
     def lol
         puts "C: LOL"
     end
end

# test1.rb
c = Child.new
c.lol # => "C: LOL" or "P: LOL" if commented out
Child.class_eval { undef_method :lol }

# Try to redefine method and call super.
class Child < Parent
     def lol
         print "LOL: "
         begin
             super
         rescue NameError => e
             puts e.to_s
         end
     end
end

c.lol # => "LOL: superclass method `lol' disabled"

# Then in test2.rb:

c = Child.new
c.lol # => "C: LOL", or "P: LOL" if commented out.

Child.class_eval { undef_method :lol }
# Try to redefine method and call super.
Child.class_eval do
     define_method(:lol) { print "LOL: "; super }
end
c.lol # => "LOL: P: LOL"

Now ... Why can I call super in the redefinition of the method using  
define_method, and not using the def ... end block? For me this seems  
like an inconsistency. First I thought it was neat that I could not  
call super in the method after using undef_method and redefining it  
again, but then I found out I could using define_method.

As the comments state, I also tried to run the code with the  
redefinition of the lol method in the Child class, but to no help.  
The output is roughly the same (P instead of C obviously).

Anybody care to shed a little light on this?

-- 
Vennlig Hilsen
Rune Hammersland



Re: Difference between define_method and def method; end

Postby ara.t.howard » Thu, 02 Nov 2006 01:10:11 GMT




<snip>


you are not redefining the method here, you are redefining the class.  if you
simply redefine the method it does what you expect:

     harp:~ > cat a.rb
     class Parent
        def lol() puts "P: LOL" end
     end

     class Child < Parent
        def lol() puts "C: LOL" end
     end

     c = Child.new
     Child.class_eval { undef_method :lol }

     class Child  #< Parent
        def lol
          print "LOL: "
          super
        rescue NameError => e
            puts e.to_s
        end
     end

     c.lol


     harp:~ > ruby a.rb
     LOL: superclass method `lol' disabled


regards.

-a
-- 
my religion is very simple.  my religion is kindness. -- the dalai lama


Re: Difference between define_method and def method; end

Postby Rune Hammersland » Thu, 02 Nov 2006 04:56:00 GMT





That is actually the same output I had. My problem (and excuse me for  
not
stating it clearly) is that if I use define_method after undef_method:

     Child.class_eval { undef_method :lol }
     c.lol # raises exception (of course)

     class Child; def lol() print "LOL: "; super end; end
     c.lol # raises exception (superclass method disabled)

     Child.class_eval { define_method(:lol) { print "LOL: "; super } }
     c.lol # prints "LOL: P: LOL"

So you see: defining the method using the def ... end block raises an
exception if you call super after the method has been undefined, while
defining it using define_method does not. I expected it to either  
raise or not
raise the exception in both cases (but do the same for both).

I hope that clarified it (although I'm not sure it did, as explaining  
things
can be hard to do even in your native language).

.. or am I still redefining the class using the class ... end block?

-- 
Vennlig Hilsen / Regards
Rune Hammersland



Re: Difference between define_method and def method; end

Postby Timothy Goddard » Thu, 02 Nov 2006 16:08:30 GMT







Hmm, very odd! You can get around this by doing something like this:

class Object
  def supercall(meth, *args)
    method_name = meth.to_s
    current_class = self.class
    m = nil
    until m
      raise NoMethodError if current_class == Object
      current_class = current_class.superclass
      if current_class.instance_methods.include?(method_name)
        m = current_class.instance_method(method_name)
      end
    end
    m.bind(self).call(*args)
  end
end

You then replace the "super" keyword with a supercall(:foo) in your
example and it works. This is much slower though.


Re: Difference between define_method and def method; end

Postby Rune Hammersland » Thu, 02 Nov 2006 21:11:18 GMT





I don't necessarily prefer the first, I prefer them to behave the  
same way.
Actually having the super method available makes more sense.

The reason I stumbled upon this is because I'm writing about  
sandboxing and
would like to explain how you can supply "safe" versions of classes  
in the
sandbox by "disabling" unsafe methods (of course it doesn't help if  
you can
simply redefine the method yourself, but it's a first step). When  
playing
around with undef_method and remove_method I found that remove_method  
only
removes method defined in the class it self (and not derived  
methods), while
undef_method prevents objects of the class from responding to the  
method (as
is explained in `ri Module.undef_method`). And then I found this  
inconsistency
in behavior.

While we're on it: any good suggestions for how to supply "safe"  
versions of
classes to the sandbox? Something like how Python's Bastion module is/ 
was
supposed to work (it's now deprecated, together with the RExec  
module). I
guess the best would be to call remove_method on the unsafe methods  
in the
classes they are defined, and hope that an attacker don't redefine  
the method
himself (which is hard to prevent).

-- 
Vennlig Hilsen / Regards
Rune Hammersland


Re: Difference between define_method and def method; end

Postby ara.t.howard » Thu, 02 Nov 2006 23:35:43 GMT




huh - i'd sworn that was the case...  looks like you are right.

sorry about that!

-a
-- 
my religion is very simple.  my religion is kindness. -- the dalai lama


Re: Difference between define_method and def method; end

Postby Rune Hammersland » Fri, 03 Nov 2006 05:28:05 GMT





I stumbled upon it by pure coincidence ... Should I report a RCR or
something like that?

-- 
Vennlig Hilsen
Rune Hammersland





Return to ruby

 

Who is online

Users browsing this forum: No registered users and 22 guest