Method Missing: Friend or Foe?- 4 mins
In Ruby when you send a message to an object, the object will look for the first method it will find in its path and execute it. If it doesn’t it will simply throw a NoMethodError:
One of Ruby’s interesting features is the
method_missing method. Amongst the many things this method allows you to do is to define default behaviour when trying to call a method that doesn’t exist:
The above can be very useful in providing meaningful feedback but it’s also used extensively in Metaprogramming.
Now you’ll wonder why I included the word “Foe” in the title. Today I was working on my TicTacToe implementation with the goal of adding a GUI to it. I was using Qt and more specifically the Ruby bindings.
As I was working and experimenting with it I was constructing various layouts and adding widgets to them:
I won’t go into detail what each piece of the code does but the key is the line that starts with
connect. There I’m essentially connecting
@button_1 to a slot containing the method
show_board which would get triggered when the button gets clicked. This is the relevant method:
Now the above works fine. My issues occurred when I was trying things out prior to figuring it out. Because Qt is written in C++ the methods are written in CamelCase so the
remove_widget above looks like
removeWidget. I appreciate the work that was put into providing this bindings in Ruby but it’s obvious that the implementations are not consistent across the board as you can see by the
windowTitle method in the constructor. My main issue though was with
method_missing. Whenever I called a method on
@buttons_layout such as
remove_widget without any parameter, I was failing the test and getting a NoMethodError even though I could see that the method existed on the object by simply calling
@buttons_layout.methods. After expressing my frustration to the rest of the guys, Daniel who had worked with the framework before suggest passing anything as an argument. I passed
nil and indeed it work.
I must of spent a good hour or more trying to understand the above because in my mind a method that takes arguments and doesn’t get passed any arguments, it returns an
NoMethodError is the last thing I would be expecting since I can see that the method exist.
I might be missing something or not know enough about the subject but surely the above does not seem right to me. I haven’t looked into the source code of qtbindings yet but I would like to see the implementation that causes such a result. In the meantime I’ll try and understand better the framework and hopefully avoid such pitfalls. Just like with anything
method_missing is a great tool which if misused can cause major issues.