 I was convinced that speaking after lunch was just the worst thing that could happen. But the morning after the party is, yeah. After talking to a few of you, I mean, people after lunch may be sleepy, but at least they're sober. I'm going to talk about method missing. So I hope that you like the idea of being stuck in here with me talking about a single method for half an hour, because that's what's going to happen. And the reason for that is that I wrote this book. So people ask me about, for example, my favorite meta programming tricks. And when I tell them that I have a soft spot for method missing, I get reactions such as this one. I thought it was scary. This was actually a very mild one. I got flamed by people that called me irresponsible for teaching newcomers about method missing because it's dangerous. And my reaction was, oh, come on, how dangerous can it be? Wimps. So I decided to do a presentation about this. Disclaimer about this. There are some uses of method missing that are not controversial. If you don't know what method missing is, because you are new to Ruby, I will try to explain it soon. Meanwhile, if you do know what it is, stuff like this, for example, this is dynamic finders from Rails, find by name and password. You can have find by name and password, find by password and name, find by name, name, password, email. You might have potentially thousands of methods. And to do this, if you have a very large namespace of methods, then you really want to use method missing. That's not controversial. That's not what I'm going to talk about. End of disclaimer, what I'm going to talk about is using method missing to remove duplication. And let's come up with a concrete example of that. Silly example, I have a class like this timetable, say, that has a few methods, a few dozens of methods. For example, I don't know, flights, or it turns information about a big string with information about flights. I don't know what. Trains, hotel shutters, what have you, a number of methods. And I want to add a feature that impacts all these methods in the same way. For example, a silly feature where you can only call these methods during normal office hours. And if you call the methods during lunch time, you will get an out for lunch string, OK? Useful. And one of the ways that you can do this is by wrapping these objects inside another object. I called it an infodesk. And this infodesk has a timetable. And it has one method for each method in the timetable. And all these methods just forward to the timetable, except that first they have this duplicated line of code that checks for lunch time. And if it's lunch time, it will just return out for lunch. And it's duplicated. It sucks in so many ways. It's so easy to get wrong. Now, how can method missing help us to remove this duplication? How does method missing work for people who don't know? What happens when you call a method on a class like infodesk? In Ruby, what happens is that each class has a chain of ancestors, typically inheritance. So infodesk inherits from object, which includes a module named kernel, and inherits from basic object. So that's the chain. When you call a method on the infodesk, Ruby will go to the bottom of the chain and look for the method there. And if it cannot find the method, it will start walking up the chain to look for the method. And if it gets to the top of the chain and it still cannot find the method, it does something funky. It starts from the bottom again, and it looks for a method named method missing. And it goes up the chain again a second time. And it will find that method this time around because there is a method missing in basic object. And that's where no method errors come from. And the twist on this is that you can override method missing with your own method missing like this. And now you can basically intercept all calls to methods that do not exist. You can use this to do something like replacing all the methods in the infodesk class with one single method missing that will get the name of the method that you call then the arguments and also the block if you're interested in that. So no duplication whatsoever, okay? And this is strange because you can still call a method such as flights, but the method is not there. You can call it, it will execute code. It looks like it's there, but it's nowhere to be found if you look at the code. So you can call it a ghost method, okay? I like drawing ghosts. This is actually my main motivator for this entire presentation. And some people would say that this use of method missing is too dangerous. You shouldn't do that because you have an alternative. The alternative looks like this. Basically you go, I won't go into the details, but basically you iterate through the instance methods of timetable and for each method in timetable you actually define on the spot a new method for the infodesk. So these are not ghost methods anymore. They are real concrete methods. Only define dynamically. You can call them dynamic method. If you are picky, they are actually dynamically defined methods. But this is basically the question that I'm asking. Should we use ghost methods or should we use dynamic methods? Okay, this is the dilemma. And I have this thing for method missing. So I was trying to show that if you do your homework and you know how to deal with it, method missing is not dangerous at all, but it's all love and unicorns. That was my original idea for the entire presentation. So I tried to check what the problems might be if you use method missing. Okay, one problem that you can have with this code, this code just works. Doesn't have any problem in itself. But assume that you want to do some refactoring. For example, you want to extract this thing, clock lunchtime, into its own method because I don't know, you want to, are you still there? Yeah. Because you want to stop it for testing or whatever. So you would just want to extract a method out of that easy. So where is the problem with this? Let's make some space, let's define the method. Okay, can you see where the problem is? Come on, do this and do that. Yeah. Was that the Sheraton, by the way, staying at the Sheraton? Did you get evacuated this morning? It works great, so much better than a normal alarm clock. I usually sleep through that shit. And so we were all having breakfast or apart from Roy who slept through that. And I had this idea. What about an alarm clock that just emits smoke? Jesus. Go to Kickstarter, do that, you have my money. Sorry, talking bullshit. Okay, where is the problem here? Yeah, yeah, yeah. You see, I talk bullshit for a while and you have the time to actually spot the problem. So it is actually a quite common problem. I just made the typo. I used an underscore in lunchtime there but not here. But usually, this kind of problem is easily spotted. I mean, I will get a very explicit error message that says, look, you don't have a method by that name and I will go like, oh, silly me, I fix it. But in this case, what happens is that we have a method missing. So when we call, is it lunchtime yet like this? This method does not exist. So it ends up calling method missing again and again. And of course, in the end, you are gonna get a system stack error. You are filling the call stack. And in this case, it's just a few lines of code. But if it's a large system, good luck finding this. You are on your own completely. So this is the first problem that you can have with method missing, call it the ghost house because basically you are creating too many ghosts. Now, anything that you can say is a ghost and you don't want that to happen and there is an easy fix for that. You simply add one or two lines at the beginning of your method missing that basically narrow down the number of ghosts that you can create. In this case, I just said, timetable, do you respond to this method? Do you have this method? If you do, then we go forth. If you don't, then we just call super which is the basic method missing with owner. So we are narrowing down. Our ghosts, easy. But now we have another problem. Talking about to respond to, the problem here is that if you go and ask to the info desk whether it responds to a method such as flies, it will say, no, I don't. It's lying to you, okay? And this is usually not a big problem, but if you start using, for example, the info desk, you wrap the info desk inside another info desk. I don't know. If you start using the object in ways that you didn't anticipate, then it can really bite you. Again, this is not a huge problem, but you should be aware of this. Basically, the object is not aware of the method it has, the methods it has. So, how to fix this? Easy, redefine or respond to. So every time you redefine method missing, you should probably override or respond to as well. In this case, it's just saying, this object has all the methods in the time table, and super means called basic response to, so it also has its own methods. And usually, this is where it stops. You don't need to do anything else to make it work. This is enough of a safety net to use method missing. But actually, no, we have another potential problem. This one is really, really sneaky. Assume that you have a method in time table that's called, for example, display. And maybe it retards a fancily formatted display with all the information for the day for a traveler. I don't know. So you expect that if you call display on the info desk, the info desk will turn around and call display on the time table, right? And actually, it doesn't happen. You get a quirky string, which seems to be the string representation of the info desk object itself. Anybody knows why this happened? Ah, yeah, yeah. It's not really an object, but yeah, you got it. It's in kernel. The problem here, remember how the entire system works? Ruby's gonna go up the chain and then it's not gonna find the method and it's gonna start from scratch, from the bottom. But actually, it's gonna find the method because there is a method by that name in kernel. It's a very seldom used method. You can easily forget about it, but it's there. So basically, you have a name clash. So this is yet another issue that you can have with method missing. You can call it the fake ghost because you think that you are calling a ghost, but that method actually does exist. So, name clashes are bad, and how do I fix that? Now, brace yourself, because this is starting to be a little bit scary. One way to fix this is to just remove all the methods that might potentially clash, okay? So I might add codes such as this one, go through all the methods in this object and remove them, except that no, I cannot blindly remove all the methods because some of those methods, so Ruby really expects them to be there. They are used inside the interpreter. For example, the methods that begin with a double underscore and the method object ID, those are absolutely essential. You don't want to remove those. And maybe there are other important methods. So you see, we are working this tightrope and it's a bit unnerving. Which methods should I remove? And the good news is that in Ruby 1.9, you don't really need to care because you already have a class that in a way has just the right amount of methods, very few methods, only the important ones, and it's basic object. So you can just inherit from basic object and you're done, that's cool, okay? You can call basic object a blank slate because it has only the minimal amount of methods. So you will reduce the chances of a clash. Okay, it seems that we are almost done, but to be picky, some people will come up with yet another issue. It's probably not gonna happen to you, but just for completeness. Think back about what Ruby does when you call a method that does not exist. It goes up the chain and blah, blah, blah, then it starts from scratch and calls method missing, which means that sometimes if you have a very, very long Ancestor's chain, and if you do a lot of calls to method missing, you might find your performance suffering for that. There is a lot of lookup going on. It's probably not going to happen to you, but it happened to Rails, for example, where pretty much everything is a call to method missing in active record, at least, and the Ancestor's chain is crazy long because they have a lot of modules. So you can call this last pitfall as nail ghost because ghost methods can be slower than regular methods and how do you fix that? Now, I'm going to hopefully blow your mind, but this is actually what Rails does, pretty much what Rails does. They do something like this. The first time you call method missing, it's just a ghost method, but it will take that chains to actually use defined method to create the method for real. So from the second call onwards, it's not a ghost method anymore. It's a dynamic method call. Call it reincarnation, if you wish, basically, yeah? First time you have a ghost, second time you don't, which is quite cool. And as I was preparing this presentation, I was patting my own back all the time because I was feeling really, really clever for coming up with all this shit, except that this code doesn't work. It throws a system stack error. Why? There is sand on basic object, but you're close. The single thing back? Thank you, sir. Okay, when I asked this in Berlin, at the European Ruby Conference, only two people could spot the problem. They were Konstantin Hase, the Sinatra guy, and Yukio Matsumoto. The problem is that we are calling singleton class here, which is a method, but we don't have the singleton class method because this is a blank slate. We removed the method when we inherited from basic object. And this is not something that I came up with to trip you up. It actually happened as I was preparing this presentation. I was like, so, okay, one, that's a little bit too much. I'm a method missing lover. I was preparing this presentation to these method missing haters, but frankly, I was scared by this. So just because, just to set things straight, I will, am I on video? Yes, I am. So I can give a public answer to the method missing haters, Jake Scruggs for them. This is the feeling moment. May I get lower lights? Jake Scruggs, sorry. You were right. And I was wrong. I loved method missing and it broke my heart. I completely fucked this one up. So the answer to the original question, should I use method missing to remove duplication from my code? No. At least not if you can use defined method instead. And because I know that you will use it anyway, I will when you do just to remember the pitfalls. You can create too many ghosts, call super. You can have your object lie to you about the methods it supports, implement or respond to. Mind your name clashes, use a blank slate. And the part about performance, how come it's not gonna happen, but just be aware, just in case. That's it, thank you. Thank you.