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
[snip]
# List the methods of Klass
Klass.methods.sort.each do |method|
Try Klass.instance_methods.
···
On 9/28/06, Martin Coxall <pseudo.meta@gmail.com> wrote:
puts "Klass##{methodName}"
end
----------------------------------------------------------------
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
···
On 9/28/06, Arnaud Bergeron <abergeron@gmail.com> wrote:
On 9/28/06, Martin Coxall <pseudo.meta@gmail.com> wrote:
[snip]
>
> # List the methods of Klass
> Klass.methods.sort.each do |method|
Try Klass.instance_methods.
You need to send define_method to the classes singleton class, and
that takes a trick:
rick@frodo:/public/rubyscripts$ cat def_class_meth.rb
#! /usr/bin/ruby
···
On 9/28/06, Martin Coxall <pseudo.meta@gmail.com> wrote:
On 9/28/06, Arnaud Bergeron <abergeron@gmail.com> wrote:
>
> On 9/28/06, Martin Coxall <pseudo.meta@gmail.com> 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.
#
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
rick@frodo:/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
rick@frodo:/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/
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