Defining methods, Javascript-style
The knowledgeable amongst you must have known that Ruby supports so called singleton methods which basically means methods can be defined on the instances of the class, rather than class itself. So, for example, you could redefine a method on a particular object and do all sorts of fun stuff. This is how it's usually done:
obj = "something" def obj.my_new_method "does nothing" end obj.my_new_method # => "does nothing"However, I like the javascript approach to this better. In javascript, function is treated as a variable you simply assign to the property of the object.
var obj = new String("something")
obj.myNewMethod = function() { return "does nothing" };
obj.myNewMethod(); // => "does nothing"
Fear not! With some meta programming you can achieve the same in Ruby. Let's see how.
module DynamicMethods
def method_missing(method, *args)
raise NoMethodError unless method.to_s[-1..-1] == "="
(class << self; self; end).class_eval do
define_method(method.to_s[0..-2].to_sym, args.first)
end
end
end
obj = "hello, friend!"
obj.extend DynamicMethods
obj.piratize = proc { self.gsub("hello", "ahoy").gsub("friend", "matey") }
obj.piratize # => "ahoy, matey!"
As you have guessed, the trick is in our DynamicMethods module. This module creates a method on the fly, by invoking a non-existent method ending with "=" and a single proc argument. Note that the proc method is evaluated in the context of the "hello, friend!" object, not it's surroundings - which is the expected behaviour when defining methods. So there you have it - instant pirate talk and method definitions javascript-style.

http://gist.github.com/296967
This allows you to assign values that aren't Procs and treats them like attributes. Also, this calls super, which is better in case something else along the class hierarchy has defined method_missing as well
But I guess for true javascript equivalence, should probably just set the value,
and then rely on saying "object.name.call(23)"
rather than expecting ruby-style method invocation.
http://gist.github.com/302269