# Define\_method confusery

**URL:** <https://www.ruby-forum.com/t/define-method-confusery/70360>\
**Category:** Ruby\
**Created:** [September 28, 2006, 6:10pm UTC](https://www.ruby-forum.com/t/define-method-confusery/70360 "2006-09-28T18:10:45Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![mjcharl](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/ac91a4/32.png) [@mjcharl](https://www.ruby-forum.com/u/mjcharl)\
**Post date:** [September 28, 2006, 6:10pm UTC](https://www.ruby-forum.com/t/define-method-confusery/70360/1 "2006-09-28T18:10:45Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![mjcharl](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/ac91a4/32.png) [@mjcharl](https://www.ruby-forum.com/u/mjcharl)\
**Post date:** [September 28, 2006, 6:16pm UTC](https://www.ruby-forum.com/t/define-method-confusery/70360/2 "2006-09-28T18:16:45Z")

</div>

On 9/28/06, Martin C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:  
[snip]

> # List the methods of Klass
> 
> Klass.methods.sort.each do |method|

Try Klass.instance\_methods.

---

<div class="post-metadata">

**Author:** ![mjcharl](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/ac91a4/32.png) [@mjcharl](https://www.ruby-forum.com/u/mjcharl)\
**Post date:** [September 28, 2006, 6:22pm UTC](https://www.ruby-forum.com/t/define-method-confusery/70360/3 "2006-09-28T18:22:47Z")

</div>

On 9/28/06, Arnaud B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> On 9/28/06, Martin C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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

---

<div class="post-metadata">

**Author:** ![mjcharl](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/ac91a4/32.png) [@mjcharl](https://www.ruby-forum.com/u/mjcharl)\
**Post date:** [September 29, 2006, 12:38am UTC](https://www.ruby-forum.com/t/define-method-confusery/70360/4 "2006-09-29T00:38:09Z")

</div>

> 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

---

<div class="post-metadata">

**Author:** ![mjcharl](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/ac91a4/32.png) [@mjcharl](https://www.ruby-forum.com/u/mjcharl)\
**Post date:** [September 28, 2006, 11:32pm UTC](https://www.ruby-forum.com/t/define-method-confusery/70360/5 "2006-09-28T23:32:01Z")

</div>

On 9/28/06, Martin C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> It doesn’t work.

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

# 

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](http://eigenclass.org/hiki.rb?Changes+in+Ruby+1.9#l18)

–  
Rick DeNatale

My blog on Ruby  
[http://talklikeaduck.denhaven2.com/](http://talklikeaduck.denhaven2.com/)
