Define_method confusery

So I have some code which adds a method to a class based on user input
like
this:


class Klass

Do nowt originally

end

Get the name of a method to add

puts “Enter the name of the method to add”
$stdout.flush

methodName = gets
methodName.chomp!

puts “Adding method #{methodName}”
$stdout.flush

Add a method called ‘methodName’ to Klass

Klass.class_eval do
define_method(methodName) do |*values|
puts “Welcome to #{methodName}!”
puts values.to_s
end
end

Try to invoke the new method

instance = Klass.new
instance.send(methodName, “—”, “+++”)

List the methods of Klass

Klass.methods.sort.each do |method|
puts “Klass##{methodName}”
end


So, the code appears to work fine, in that the send() method is able to
call
the newly created method. So, does anyone know why is it when I list the
methods of the class Klass afterwards, the new method does not appear?

Also, is it possible to use define_method() to add class methods to
classes,
rather than just instance methods? I can’t seem to get it to work.

Regards,

Martin

On 9/28/06, Martin C. [email protected] wrote:
[snip]

List the methods of Klass

Klass.methods.sort.each do |method|

Try Klass.instance_methods.

On 9/28/06, Arnaud B. [email protected] wrote:

On 9/28/06, Martin C. [email protected] wrote:
[snip]

List the methods of Klass

Klass.methods.sort.each do |method|

Try Klass.instance_methods.

Aha! That would do it. Thanks.

Do you know if it’s possible to add class methods to classes using
define_method() then? It seems to work if I do a

define_method(“Klass.”+methodName)

However, when I then try to invoke using

Klass.send(methodName, “some stuff”)

It doesn’t work.

Regards,

Martin

You need to send define_method to the classes singleton class, and
that takes a trick:

Okay, I think I understand why that is, but I’d better re-read
Programming Ruby on Singleton classes.

def create_class_method(name, klazz, meth=nil, &b)
klazz_klazz = class << klazz; self; end
create_method(name, klazz_klazz, meth, &b)
end

Okay, I can kind of see that. I think. Um.

Thanks very much.

Martin

On 9/28/06, Martin C. [email protected] wrote:

It doesn’t work.

You need to send define_method to the classes singleton class, and
that takes a trick:

[email protected]:/public/rubyscripts$ cat def_class_meth.rb
#! /usr/bin/ruby

def create_method(name, klazz, meth = nil, &b)
raise ArgumentError “give method or block, but not both” if meth &&
block_given?
if block_given?
klazz.send(:define_method, name, &b)
else
klazz.send(:define_method, name, meth)
end
end

def create_class_method(name, klazz, meth=nil, &b)
klazz_klazz = class << klazz; self; end
create_method(name, klazz_klazz, meth, &b)
end

class Foo
end

create_method(:foo_inst_meth, Foo) {“This is an instance method of Foo”}
create_class_method(:foo_class_meth, Foo) {“This is a class method of
Foo”}

puts Foo.new.foo_inst_meth
puts Foo.foo_class_meth

[email protected]:/public/rubyscripts$ ruby def_class_meth.rb
def_class_meth.rb:5: warning: parenthesize argument(s) for future
version
This is an instance method of Foo
This is a class method of Foo
[email protected]:/public/rubyscripts$

Note that in ruby 1.9 send won’t call a private method anymore, you
need to use funcall instead.
http://eigenclass.org/hiki.rb?Changes+in+Ruby+1.9#l18


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs