Tuesday, July 15, 2008

Ruby: Move a Method from a Class to a Module Definition

I was recently working with a framework that reopened and defined a method on Object. I wanted the behavior of the framework, but I also wanted to define my own behavior. This is generally the case for alias_method_chain or one of the other Alternatives for Redefining Methods, but my circumstances (to be discussed in a subsequent post) prevented me from using one of the better known solutions.

The solution that worked for me was to move the original method definition to a module.

class Speaker
def say_hello
"hello"
end
end

module EnglishSpeaker
expects_method = Speaker.instance_method(:say_hello)
define_method :say_hello do |*args|
expects_method.bind(self).call(*args)
end
end

class Speaker
undef say_hello
end

Speaker.new.say_hello # => -:18: undefined method `say_hello' for #<Speaker:0x285b4> (NoMethodError)
Speaker.new.extend(EnglishSpeaker).say_hello # => "hello"

You may never need this technique, I only needed it once in the past 2.5 years. But, when it applied I found it to be significantly better than the alternatives.

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.