Quantcast

Ruby on Rails, Io, Lisp, JavaScript, Dynamic Languages, Prototype-based programming and more...

Technoblog reader special: $10 off web hosting by FatCow!

Thursday, August 03, 2006

Dynamically Add Methods to Classes Through their Objects in Ruby

Playing with the implementation of a new library I am working on called starfish (I will blog about it shortly), I came up with this fun little Ruby hack that makes Ruby seem more like a prototype-based language than it already does.


class Foo
def method_missing(name, *args)
if name.to_s =~ /(.*)=$/ && args[0].is_a?(Proc)
self.class.instance_eval do
define_method($1, args[0])
end
else
super
end
end
end

f = Foo.new
f.greet = lambda {|t| "Hello #{t}!"}
f.greet "Lucas Carlson" # => Hello Lucas Carlson!

j = Foo.new
j.greet "World" # => Hello World!


Hope you enjoy it as much as I do and I can't wait to show you how I am using it!

You should follow me on twitter here.

Technoblog reader special: click here to get $10 off web hosting by FatCow!

13 Comments:

Anonymous Anonymous said...

What's wrong with require "ostruct" ?

9:20 AM, August 04, 2006

 
Blogger Lucas Carlson said...

OpenStruct is a great library, but does not add arbitrary methods at run time. For example:

require 'ostruct'
x = OpenStruct.new
x.bar = lambda{|x|puts x}
x.bar(1) # => #Proc:0x013e8b34@(irb):8

That is not what you would expect, you want it to print out 1.

10:34 AM, August 04, 2006

 
Anonymous Anonymous said...

That's pretty cool. As I do not seem to be very imaginative today, could you give an example of where this technique may be useful?

2:32 PM, August 04, 2006

 
Blogger Lucas Carlson said...

I am using it a library I am about to announce, so you will see a great use in a few days.

2:34 PM, August 04, 2006

 
Anonymous Anonymous said...

if the only thing is invoking that lambda in a method, just:
define_method($1,&args.first)

2:58 PM, August 04, 2006

 
Anonymous Anonymous said...

oops, I didn't escape the & :|

3:00 PM, August 04, 2006

 
Blogger Lucas Carlson said...

Good point, I have changed that in the code example, thanks.

4:01 PM, August 04, 2006

 
Blogger jChris said...

that's fun!

4:19 AM, August 05, 2006

 
Anonymous Anonymous said...

hi,
a really good idea, oh i've just realised that you could call self.class.send to get to the private method rather than use instance_eval, I suppose it's a little bit shorter.

if name.to_s =~ /(.*)=$/ && args[0].is_a?(Proc)
self.class.send(:define_method, $1, args[0])
else
super
end

1:53 AM, August 06, 2006

 
Blogger Lucas Carlson said...

I have posted the way I am using this in a new blog post.

2:07 PM, August 23, 2006

 
Blogger geirfugl said...

Really good stuff. Thanks!

8:57 AM, January 18, 2007

 
Anonymous Anonymous said...

i buy hydrocodone at buy hydrocodone - can't find any cheaper

5:48 AM, January 28, 2007

 
Anonymous Ramonita said...

This is fantastic!

2:31 AM, September 26, 2013

 

Post a Comment

Subscribe to Post Comments [Atom]

<< Home

 

If you like this blog, you might also like top photography schools.