

Do you know Ruby’s ‘Chainsaw’ method? - IndianGuru
http://rubylearning.com/blog/2010/10/07/do-you-know-rubys-chainsaw-method/

======
JangoSteve
I prefer to use define_method over method_missing when "metaprogramming". It
allows you to explicitly define your "metamethods" up-front.

Using his example of the DoNotDisturb wrapper around InformationDesk, you
could easily do something like:

    
    
      [:emergency, :flights, :local_transports, :hotels].each do |name|
        define_method(name) do
          check_lunch_break unless name == :emergency
          @desk.send(name)
        end
      end
    

Now you don't get the side effect of screwing up your exception handling and
having to walk on eggshells with the rest of your coding in that class.

The other thing I like about this method is that it gets evaluated once, and
then those methods exist. With method_missing, every single time you call one
of those methods, it has to go all the way up the chain to find that method
until it finally hits method_missing.

EDIT: Oh, and if nothing else, you can at least put the define_method inside
the method_missing (I had a project that required method_missing once, so this
is what I did). That way, it only has to crawl all the way up the inheritance
chain once, then that method gets defined on your class, so subsequent calls
to that method don't have to go all the way up the chain again.

Might not be much performance gain in Ruby, but when programming a rails app
(where you're likely working on a class that inherits from ActiveRecord and 10
other classes), it helps.

~~~
warfangle
While I know this is a rubyist thread, I want to chime in as a Javascript
developer. You can almost do the same thing there - joy! Probably not the best
way to do it, but it's 3AM and I'm writing off the top of my head. And it's a
_little_ bit messy. And it gets rid of that pesky emergency case.

Within the object constructor:

    
    
      // assuming the desk object was inherited and accessible. There are several ways to do this.
      var thisContext = this; // unless you want to do some weird stuff with calling a function that returns a function that calls a function
      ["flights", "local_transports", "hotels"].forEach(function(fn) {
        thisContext[fn] = function() {
          check_lunch_break && desk[fn](arguments);
        };
      });
      

Granted, this doesn't get your methods on the prototype, and will incur a cost
every time you create one of these objects. If you properly inherited from the
desk class, it will overwrite them. And the emergency function will work just
fine, if defined on desk.

~~~
troels
Nitpickery indeed, but that won't work as expected. `fn` can be reused within
the loop, depending on the runtime, so all methods will end up calling the
same `desk[fn]`.

~~~
sharkbrainguy
I think you might have misread the code.

Each `fn` is bound exactly once, `forEach` is not a loop.

~~~
troels
Touché

------
jhickner
There's actually a fairly safe way to use method_missing. Just remember to
call super if none of your conditions are met, that way you'll still get
errors when commands are misspelled. You really shouldn't ever use
method_missing without that.

He probably also should be checking if @desk actually has a method with the
provided name (with @desk.respond_to?(method_name)) before attempting to call
it.

~~~
tomafro
He should also define respond_to? on the DoNotDisturb class. Relying on
method_missing to pass calls to respond_to? to the proxied class will not
work, as it is defined in Object. Responding to a method when respond_to?
returns false breaks the class contract.

~~~
nusco
From the OP: I agree with you guys (or gals) on both calling super and
redefining respond_to?(). Those are two of the "caveats" I mentioned at the
end of the original post. I considered mentioning them explicitly, but the
post is long enough already.

------
jrockway
method_missing / AUTOLOAD is a great way to break any tools that rely on being
able to introspect your classes.

For something as simple as this, just add the methods to the class in a loop.
Then you class works just like every other class; no introspection is broken.
It's also faster at runtime.

~~~
tomafro
I can see how method_missing can break introspection, but I don't see how the
same is true for Autoload. Could you give an example?

~~~
draegtun
I believe _jrockway_ is referring to AUTOLOAD in Perl (ie. its equivalent of
Ruby's _method_missing_ ).

ref: <http://perldoc.perl.org/perlsub.html#Autoloading>

------
jfager
_When I work with Java or C#, I accept this kind of code duplication as a fact
of life._

Java has had dynamic proxies since 1.4. As long as you're working with
interfaces, you can do the exact same thing as the example given in this post.

~~~
city41
And the new dynamic support in C# gives it a direct equivalent to
method_missing.

~~~
nusco
From the OP: I used dynamic proxies in both Java and C#. For example, I wrote
the annotations introspector for Hibernate Annotations, and a memcached
wrapper for a C# project. Both are proxy-based.

However, using dynamic proxies in Java feels like going against the grain of
the language: strong typing and dynamic calls don't really like each other. As
a result, you usually resort to Java/C# dynamic proxies only when you have no
other option. I've yet to see anyone using a dynamic proxy just to remove
duplication in a Java class.

C# dynamics might make dynamic proxies less clumsy in that language. Will try.
Do you have experience with them already?

~~~
jfager
I haven't seen them used much in any of the open source Java projects I'm
familiar with, I agree. We used them fairly extensively at my previous job,
though, for implementing a mix-in pattern for boilerplate-free service
endpoints, and they worked nicely. Outside of that, I use them al the time
during development to add quick-and-dirty method call tracing when I'm trying
to debug something.

I personally think that they're very much underused, and having based an
interview question on them for a while, not well-known at all.

------
xentronium
For me method_missing looks more like an anti-pattern because it's easy to
miss, it's hard to debug, it's impossible to scan visually, it messes up code
lookup if you use IDE, it messes up search if you don't.

------
bluesnowmonkey
A better analogy to magic methods would be dynamite. There are a few
situations where you should use it, but not many, and generally it's when
there's no other option.

His example violates the principle that objects should represent things. (What
is a DoNotDisturb?) Back to OOP school, metaprogrammer!

~~~
nusco
From the OP: I considered changing the names because I had the same concern,
but in the end I figured that the current name was good enough for a toy
example. In hindsight, you're probably right I should have used other names
(although your sneering tone is not really necessary).

------
callmeed
I'm going through the author's book right now ( _Metaprogramming Ruby_ ). It's
great.

------
zeteo
FP fanboys will laugh so hard at this. The proper way to deal with
duplication, as described in this article, is of course to use functors. With
a general method_missing(), your compiler will not even catch spelling errors
anymore.

~~~
epochwolf
> With a general method_missing(), your compiler will not even catch spelling
> errors anymore.

Ruby isn't compiled. Whether or not it catches typos is up to your logic. All
of my method_missing calls eventually hand off to the parent class's
implementation when they can't match anything.

> The proper way to deal with duplication, as described in this article, is of
> course to use functors.

Except this is ruby. Ruby has modules to deal with duplication between classes
and code blocks (closures, which can be bound to variables) for general use.
It also allows for a rather clean implementation of the proxy design pattern
via method_missing. Anything dealing with classes assumes OOP, not FP.

I only have begun to figure out that I don't know anything about FP but your
comment seems rather absurd in this context.

------
joshd
"I use method_missing()to remove duplication ... On the other hand, I usually
think twice about using method_missing() for cosmetic reasons, like getting
cool method names such as find_by_name_and_address()."

That seems backwards to me. I use magic methods to define methods that can
only be defined at run time, like his example of creating methods based on
schema introspection.

Using magic methods breaks a lot of tools: IDE code completion, reflection,
documentation generation so I always explicitly define methods unless it's not
possible.

------
pkulak
I've found that the only good time to use method_missing is when I'm wrapping
an object and need to send all but a couple methods through to it untouched.
I've really never used it for anything else.

------
scott_s
I don't do any Ruby, but: can someone give a non-contrived situation where you
would want to do this? What problem does this solve?

~~~
draegtun
Good example would be XML/HTML builder. For eg in Ruby
<http://builder.rubyforge.org/>

    
    
      require 'rubygems'
      require_gem 'builder'
    
      builder = Builder::XmlMarkup.new(:target=>STDOUT, :indent=>2)
      builder.person { |b| b.name("Jim"); b.phone("555-1234") }
      
      # Prints:
      # <person>
      #   <name>Jim</name>
      #   <phone>555-1234</phone>
      # </person>
    

Also see this recent HN thread: <http://news.ycombinator.com/item?id=1626018>

~~~
scott_s
And why would you do this instead of just defining a print method that takes
the XML tag and content as separate parameters?

~~~
draegtun
Purely for aesthetic reasons.

Instead of:

    
    
        builder.person do |b| 
            b.name("Jim")
            b.phone("555-1234")
        end
    

You could write it like this:

    
    
        builder.tag!('person') do |b|
            b.tag!('name', "Jim")
            b.tag!('phone', "555-1234")
        end

~~~
scott_s
Right, which is what I'm trying to understand: what does this allow you to do
that is not just a cute way to call a method?

I think the ActiveRecord example below is the answer I'm looking for, since it
creates a method at runtime based on information that did not exist until
runtime. But I need to read up on it to understand it.

~~~
draegtun
Personally I find aesthetics an important part of programming. If it _looks_
good to me then it often means I'm doing something right!

So I don't view it has _cute_ but more it being _succinct_.

~~~
scott_s
I also find aesthetics important, but I don't find this more aesthetically
pleasing; it pings the "something's wrong" feeling. Being succinct is _a_
goal, but it's not the _only_ goal.

~~~
draegtun
Yes its subjective. There will always be a difference in view between what is
_cute_ and what is _not cute_ (and also what I think is _cute_ today may also
not hold true tomorrow!).

