Overload method in module_eval, how?

I want to overload a testcase method with debug-enabling wrapper.
But it doesn’t seems like my Object#debug method gets called at all.

Any ideas how to do this ?

···


Simon Strandgaard

ruby test_dbg.rb
Loaded suite TestDbg
Started
F
Finished in 0.008819 seconds.

  1. Failure:
    default_test(TestDbg) [test_dbg.rb:31]:
    No tests were specified.

1 tests, 1 assertions, 1 failures, 0 errors

expand -t2 test_dbg.rb
require ‘test/unit’

class Object
def self.debug(*args)
args.each{|method|
name = method.id2name
org = “debug”+name
code=<<MSG
alias #{org} #{name}
def #{name}(*a,&b)
$stdout.puts(“before”)
#{org}(*a,&b)
$stdout.puts(“after”)
end
private :#{org}
MSG
module_eval code
}
end
end

class TestDbg < Test::Unit::TestCase
def test_x
assert_equal(true, true)
end
debug :test_x # uncomment me, and it works!
end

if $0 == FILE
require ‘test/unit/ui/console/testrunner’
Test::Unit::UI::Console::TestRunner.run(TestDbg)
end

class Object
def self.debug(*args)
args.each{|method|
name = method.id2name
org = “debug”+name
code=<<MSG
alias #{org} #{name}
def #{name}(*a,&b)

     def #{name}(&b)
    $stdout.puts("before")
    #{org}(*a,&b) 
       #{org}(&b)
    $stdout.puts("after") 
  end
  private :#{org}

MSG
module_eval code
}
end
end

class TestDbg < Test::Unit::TestCase
def test_x

The arity for a test method must be == 0

···

Guy Decoux

[snip]

  def #{name}(*a,&b)
     def #{name}(&b)

[snip]

    #{org}(*a,&b) 
       #{org}(&b)

The arity for a test method must be == 0

Thanks Guy.

Though, now I don’t understand why my example didn’t work?
How to make it general so it works for an arbitrary number of arguments ?

···

On Mon, 10 Nov 2003 13:27:41 +0100, ts wrote:


Simon Strandgaard

Though, now I don’t understand why my example didn’t work?

Because the new method that you have defined was

def test_x(*a, b)
end

This give an arity -1, and runit reject these methods it keep only methods
with a zero arity

How to make it general so it works for an arbitrary number of arguments ?

You can’t give an arbitrary number of arguments for a test method

···

Guy Decoux

DrainBammage, thats obvious. Thanks.

BTW: I wonder why the last “p instance_methods” doesn’t output anything?

···

On Mon, 10 Nov 2003 13:47:46 +0100, ts wrote:

Though, now I don’t understand why my example didn’t work?

Because the new method that you have defined was

def test_x(*a, b)
end

This give an arity -1, and runit reject these methods it keep only methods
with a zero arity

How to make it general so it works for an arbitrary number of arguments ?

You can’t give an arbitrary number of arguments for a test method


Simon Strandgaard

ruby test_dbg.rb
[“test_x”]
Loaded suite test_dbg
Started

Finished in 0.002346 seconds.

1 tests, 1 assertions, 0 failures, 0 errors

expand -t2 test_dbg.rb
require ‘test/unit’

class Object
def self.debug(*args)
p instance_methods(false)
args.each{|method|
name = method.id2name
org = “debug”+name
arguments = (method.arity > 0) ? “(*a,&b)” : “(&b)”
code=<<MSG
alias #{org} #{name}
def #{name}#{arguments}
$stdout.puts(“before”)
#{org}#{arguments}
$stdout.puts(“after”)
end
private :#{org}
MSG
module_eval code
}
p instance_methods(false) # No output, why ?
end
end

class TestDbg < Test::Unit::TestCase
def test_x
assert_equal(true, true)
end
debug :test_x
end

if $0 == FILE
require ‘test/unit/ui/console/testrunner’
Test::Unit::UI::Console::TestRunner.run(TestDbg)
end

BTW: I wonder why the last “p instance_methods” doesn’t output anything?

I don’t understand, you want to say that you don’t see this ?

ruby test_dbg.rb
[“test_x”]
^^^^^^^^^^

···

Guy Decoux

I do a print both before and after. Only the first print statement
outputs something. The second doesn’t output anything?

It should output the same as the first print-statement, but I get nothing.

any ideas to what can cause such a problem ?

···

On Mon, 10 Nov 2003 15:19:18 +0100, ts wrote:

BTW: I wonder why the last “p instance_methods” doesn’t output anything?

I don’t understand, you want to say that you don’t see this ?

ruby test_dbg.rb
[“test_x”]
^^^^^^^^^^


Simon Strandgaard

any ideas to what can cause such a problem ?

args.each{|method|
name = method.id2name
org = “debug”+name
arguments = (method.arity > 0) ? “(*a,&b)” : “(&b)”

svg% ruby -e ‘def test_x() end; :test_x.arity’
-e:1: undefined method `arity’ for :test_x:Symbol (NoMethodError)
svg%

svg% ruby -e ‘def test_x() end; p method(:test_x).arity’
0
svg%

and you can have an arity < 0

···

Guy Decoux

changing so it becomes (arity != 0), will that be ok?

Still only the first output statement are working.
I don’t understand why the successive print-statements doesn’t output
anything. Any hints ?

···

On Mon, 10 Nov 2003 15:48:22 +0100, ts wrote:

any ideas to what can cause such a problem ?

args.each{|method|
name = method.id2name
org = “debug”+name
arguments = (method.arity > 0) ? “(*a,&b)” : “(&b)”

svg% ruby -e ‘def test_x() end; :test_x.arity’
-e:1: undefined method `arity’ for :test_x:Symbol (NoMethodError)
svg%

svg% ruby -e ‘def test_x() end; p method(:test_x).arity’
0
svg%

and you can have an arity < 0


Simon Strandgaard

ruby test_dbg.rb
[“test_x”]
Loaded suite test_dbg
Started

Finished in 0.003568 seconds.

1 tests, 1 assertions, 0 failures, 0 errors

expand -t2 test_dbg.rb
require ‘test/unit’

class Object
def self.debug(*args)
p instance_methods(false)
args.each{|m|
name = m.id2name
org = “debug”+name
n = method(m).arity
puts “method=#{name} arity=#{n}” # No output, why ?
arguments = (n != 0) ? “(*a,&b)” : “(&b)”
code=<<MSG
alias #{org} #{name}
def #{name}#{arguments}
$stdout.puts(“before”)
#{org}#{arguments}
$stdout.puts(“after”)
end
private :#{org}
MSG
module_eval code
}
p instance_methods(false) # No output, why ?
end
end

class TestDbg < Test::Unit::TestCase
def test_x
assert_equal(true, true)
end
debug :test_x
end

require ‘test/unit/ui/console/testrunner’
Test::Unit::UI::Console::TestRunner.run(TestDbg)

Still only the first output statement are working.
I don’t understand why the successive print-statements doesn’t output
anything. Any hints ?

I’ve given the hint : method is a Symbol, and the method Symbol#arity is
not defined.

You must first call Kernel#method with the symbol as argument and then
call arity

svg% ruby -e ‘def test_x() end; method = :test_x; p method(method).class’
Method
svg%

svg% ruby -e ‘def test_x() end; method = :test_x; p method(method).arity’
0
svg%

···

Guy Decoux

I think I do symbol2method lookup wrong. How does I lookup
the symbol in the instance namespace ?

···

On Mon, 10 Nov 2003 16:43:20 +0100, ts wrote:

Still only the first output statement are working.
I don’t understand why the successive print-statements doesn’t output
anything. Any hints ?

I’ve given the hint : method is a Symbol, and the method Symbol#arity is
not defined.

You must first call Kernel#method with the symbol as argument and then
call arity

svg% ruby -e ‘def test_x() end; method = :test_x; p method(method).class’
Method
svg%

svg% ruby -e ‘def test_x() end; method = :test_x; p method(method).arity’
0
svg%


Simon Strandgaard

ruby test_dbg.rb
[“test_x”]
symbol = test_x
ERROR: symbol2method failure, #<NameError: undefined method test_x' for class Class’>
method =
method.class = NilClass
Loaded suite test_dbg
Started

Finished in 0.002409 seconds.

1 tests, 1 assertions, 0 failures, 0 errors

expand -t2 test_dbg.rb
require ‘test/unit’

class Object
def self.debug(*args)
p instance_methods(false)
args.each{|symbol|
puts “symbol = #{symbol}”

  begin
    meth = method(symbol)
  rescue => e
    puts "ERROR: symbol2method failure, " + e.inspect
  end
  puts "method = #{meth}"
  puts "method.class = #{meth.class}"
  
  n = meth.arity
  puts "arity=#{n}" 

  name = symbol.id2name
  org = "_debug_"+name
  arguments = (n != 0) ? "(*a,&b)" : "(&b)"
  code=<<MSG
  alias #{org} #{name}
  def #{name}#{arguments}
    $stdout.puts("before")
    #{org}#{arguments}
    $stdout.puts("after") 
  end
  private :#{org}

MSG
module_eval code
}
p instance_methods(false)
end
end

class TestDbg < Test::Unit::TestCase
def test_x
assert_equal(true, true)
end
debug :test_x
end

require ‘test/unit/ui/console/testrunner’
Test::Unit::UI::Console::TestRunner.run(TestDbg)

class Object
def self.debug(*args)
p instance_methods(false)
args.each{|symbol|
puts “symbol = #{symbol}”
begin
meth = method(symbol)

       meth = instance_method(symbol)
···
  rescue => e
    puts "ERROR: symbol2method failure, " + e.inspect
  end

Guy Decoux

Guy you are ruby-wizard #1.
All my problems has been swept away.

Thanks… you have helped so many times… I think I+others own you
some beers someday :wink:

···

On Mon, 10 Nov 2003 17:17:52 +0100, ts wrote:

class Object
def self.debug(*args)
p instance_methods(false)
args.each{|symbol|
puts “symbol = #{symbol}”
begin
meth = method(symbol)

       meth = instance_method(symbol)
  rescue => e
    puts "ERROR: symbol2method failure, " + e.inspect
  end


Simon Strandgaard