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!

12 Comments:
What's wrong with require "ostruct" ?
9:20 AM, August 04, 2006
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
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
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
if the only thing is invoking that lambda in a method, just:
define_method($1,&args.first)
2:58 PM, August 04, 2006
oops, I didn't escape the & :|
3:00 PM, August 04, 2006
Good point, I have changed that in the code example, thanks.
4:01 PM, August 04, 2006
that's fun!
4:19 AM, August 05, 2006
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
I have posted the way I am using this in a new blog post.
2:07 PM, August 23, 2006
Really good stuff. Thanks!
8:57 AM, January 18, 2007
i buy hydrocodone at buy hydrocodone - can't find any cheaper
5:48 AM, January 28, 2007
Post a Comment
<< Home