 so I'll move at a brisk pace if I'm overwhelming you. Just raise a hand, I'll slow it down a little bit. So, how y'all doing? I'm Jay McAvren, I wrote this thing. And this is Messenger, the complete story of Method Lookup in Ruby. This talk's gonna take place in two major parts. The first is all about methods defined on classes, including some places you might not expect them to be. Second part's all about modules. So, classes part, we're gonna start in a slightly unusual place. Singleton methods. Those are methods that are defined on only a single object. If you've ever stubbed methods out for a test, you've used singleton methods. So, for example, we got a WebSpider class here. It sends out an actual HTTP get request across the network and returns whatever HTML it gets back from the remote server. You probably don't want that in your test, though. So, this test right here, you can see it creates a new WebSpider object, it calls get, and that sends an actual network request. You don't want your test to have to wait for that and you don't want whatever random response you get back from the remote server. You want it quick and you want it predictable. That's a good alternative for writing a singleton method to overwrite it. So, here's a quick singleton method. We create a WebSpider object and we define a new get method that just always returns a static HTML string. It's fast, it's predictable. Now, let's take a look at how Method Lookup works with those. So, to create a singleton method, we need an object for starters and before we can create an object, we're gonna need a class. So, here is my class. I wanna create an instance of my class behind the scenes, Ruby will create a singleton class specific to that object and you can access any object singleton class via the singleton class method. So, there's the output you'll see if you call singleton class on our new object. Now, why does Ruby do this? Cheap reason is consistency. The same logic that lets you call methods on an object's class also lets you call methods on its singleton class. When we define singleton methods on an object, they're added to its singleton class and that class makes the methods available exclusively to that object. So, we define a singleton method here and it'll live on our singleton class. When you call a method on an object, Ruby dispatches a message to that object looking for that particular method. Ruby's first stop in its search for a method is always gonna be the object singleton class because that's what the object refers to first. And as soon as Ruby finds a method with a matching name, it'll invoke it. Now, what would happen if we got rid of that singleton method and define a method by the same name on the class instead? If we call my method on the object, Ruby will look on the singleton class first but there's no method by that name there. Well, where can the method be found? Each class maintains a pointer to the next class that Ruby should look on for methods. So, the ancestors method, that's your cheat sheet for understanding the places that Ruby's going to look for a given method. And you can access that list of classes that Ruby's going to look on via that ancestors method. So, here we create an instance of my class, call singleton class on that to get the singleton class and call the ancestors method on that. And we get this array in response, our singleton class is up first and it's followed by my class. That's the place that Ruby's going to look next when it doesn't find that method on the singleton class. So, when Ruby fails to find my method on the singleton class it gets directed to the next class on the chain, my class goes there, invokes the method and we're good to go. Now, suppose we were to move my method again to a superclass of my class. So, we define my method up there on my superclass and say that my class is a subclass of that. We can create an instance of my class which will get us a singleton class. If we call ancestors on that singleton class again we can see all the places that Ruby will look for my method. It starts of course with the singleton class, proceeds to my class as before and the new addition here is my superclass. So, we've got our output from the ancestors method up there and you can see it exactly mirrors the places that Ruby looks for the method. It starts with the singleton class, moves on to my class, moves on to my superclass where it finds my method and invokes it. Now, what happens if a method appears in more than one place in the lookup chain? For example, if we define it on my superclass and then define it on my class as well. If a method or if a subclass method has the same name as a superclass method it'll override that superclass method. Ruby will simply invoke the first method with a name match in the one it's looking for and stop. The my method on my superclass never gets invoked. But what if you wanna call that overwritten method? Well, you can just use the super keyword within the overriding method. That'll cause Ruby to resume its search on the next class in the chain. So it proceeds to my superclass, finds my method there and invokes that as well. Okay, slides are all well and good of course but I find that actually doing stuff in a terminal makes things a little bit clearer. Let's play around with some classes from the terminal. So here we've got a superclass and a subclass that derives from it. Whoops, I skipped right past it, I'm sorry. This is a prerecorded video. Y'all don't wanna watch me type in real-time, trust me. Okay, so we've got a superclass with my method on it that simply prints the class name and then we've got a subclass where we'll override my method and call super as well. We create an instance of my class and then we're gonna override my method on the singleton class as well and call super there. We'll access the singleton class and print the ancestors list for it and then invoke the method. So if we drop back to a shell and invoke it, you see our ancestors list starts with the singleton class proceeds to the subclass and the superclass follows that and it exactly reflects the order that the print statements follow when you call my method singleton class first, super invokes my method on my class, super there invokes my method on my superclass. Now what would happen if you were to call a method that doesn't exist? Well first Ruby will search the entire ancestors chain looking for the method you call. So if we call a method named non-existent pass at the arguments one and two, Ruby will proceed through the entire method lookup chain looking for that non-existent method but when it doesn't find it, it'll call another method named method missing and the search will start over on the singleton class. It'll proceed through the entire lookup chain and there's a default version of method missing on the basic object class which all Ruby classes inherit from. That raises the exception that you're probably used to seeing no method error but you can also override method missing in your own classes. So up here on my superclass we override method missing. We take three parameters, the name of the method that was invoked and two arguments. So first Ruby will look for the method name that you actually call that non-existent method. It'll go right past that method missing definition looking for it and if it doesn't discover it, it'll start back over at the singleton class looking for a method named method missing. It'll find it there on my superclass and invoke it and like I said, Ruby passes the name of the method that you attempted to call to it as the first argument plus any arguments you called it with after that. Okay, let's take a look at class methods. You know class methods, they're methods you can call in the class itself without needing to create an instance of it first. So up here we define a class method on my class. We say def self and the name of the method we wanna define instead of just def and the method name. And then we can invoke that without creating an instance of my class first. We just say my class dot class method. There's alternate ways to define class methods. You can use the class constant instead of self within the class body or you can define a class method outside of the class altogether, again, using the class constant. Now let's take a moment and compare that class method declaration where we use the class constant to a singleton method declaration. They look pretty similar, right? The truth is in Ruby, a class method is just a singleton method on the class. A class is just another object to the instance of the class class. And since the class is an object, it has a singleton class of its own. That singleton class lets us define singleton methods on it, of course. Once you call a class method, Ruby will find it on the singleton class and invoke it. You can confirm for yourself that my class is an instance of class by calling class on it. And there you see the class class in response. You can also call singleton class on the class object if you want to take a look at that singleton class. So as is this notation work where you say def self and the class method name within the class body. Within the body of a class, Ruby sets self to point to that class. So def self.class method is exactly equivalent to def my class.class method. And the result is the same, a singleton method on the class that you can call. What about methods defined at the top level? Within a Ruby source file, you can just declare methods and call them without surrounding them in a class or a module. And you can call them immediately after defining them without needing to create instances of any class first. The way it works behind the scenes is pretty simple. Top level methods just get defined as private methods on the objects class. And since all other classes inherit from object, you can call methods defined at the top level from any instance method of any class. So here we create my class to find call my method within it. And we could call that method defined at the top level from within that instance method. Ruby will start at search at the singleton class, proceed to, sorry, proceed all the way up to the object class where it finds my method and invokes it. But then how can you call the method at the top level? After all, what we're invoking here is a private method and we're not within a class. Well, the secret is Ruby just sets self to an instance of the object class when you're at the top level, meaning you don't have to define a recipient when you call the method. You can see here that we print out self and we get mean in response, which if we check the class of that object, the class is object. At the top level, self gets set to an instance of object and since self is the implicit receiver of that method call and it's an instance of an object, the whole thing just works. All right, so that's everything for classes. Now let's move on to modules, which work behind the scenes a lot like classes. You can define methods on them after all. And you can also use a module kind of like a superclass by mixing the module into a class. Doing so will add the module to the ancestors list of the class. So if we take a look at the ancestors of my class, you see my class comes up first followed by my module kind of as if it was a superclass. In fact, internally, Ruby will treat the module as if it was a class. That means the method lookup works the same with a mix in as with a superclass. So we create an instance of my class down there, invoke my method on it. When we create that instance, it creates a new singleton class. Ruby starts its search there, the singleton class moves on to my class, because that was what was next in the ancestors list, and then moves on to my module where it finds my method and invokes it. Since mix-ins use the same lookup mechanism as classes, all the same rules apply. For example, method overriding. We can override my method within my class. Ruby will encounter that first when you invoke the method and the my method on my module never gets invoked. Super works as well. You can use super within the overriding class or within the overriding method on my class, and that'll invoke my method up on my module. Again, just as if it was a superclass. So you can override a method from a module with a method from a class, but not vice versa. Not if you use include. So let's suppose that we had a method on my class that throws an exception, and you want to override it using my module. Unfortunately, if you use include in my class, it's not gonna work. The reason is that the include method adds the module after the class in the ancestors list, meaning that my method on my class overrides the method on the module. And that's what Ruby encounters first. It invokes it, and it throws an exception. And we can confirm all this if we call the ancestors method on my class. You'll see that my class is first in the list followed by my module. However, if you were to use the prepend method instead of include to mix the module in, that'll add it to the lookup chain before the class. So let's use prepend and let's call ancestors again, and you can see the difference. My module appears first followed by my class. Prepend allows the module method to override the class method. So we use prepend here, which makes the module appear first in the lookup chain, causing my method on my module to override my method from my class. It finds that first, invokes it, and no exception gets thrown. All right, back to the console to play around with modules a little bit. So we've got two modules here, one of which we include into my class and the other of which we prepend. We're gonna define a method named my method that simply prints the module name. We're gonna define that same method within prepended module, but we'll use super there, and we'll define it on the class as well, and I use super there as well. We'll create a new instance of my class, call ancestors on it, and then invoke my method. And if we drop back to the shell and run that, you'll see that once again, our ancestors list matches the order of output when we call the method. The prepended module comes first, then the class, then the included module. Okay, let's wrap up our tour of modules with refinements. The refinements feature was added in Ruby 2.0 and improved in Ruby 2.1. Basically the goal of it, as hopefully you all saw in James Adams talk earlier, was to make monkey patching safe again. Let's go with an example, just to make things a little bit clearer. Let's suppose you wanna change the way that the capitalize method on string instances works. So let's say you've got a bunch of movie titles and you want them in title case where each word is capitalized. Unfortunately, the default version of capitalize, capitalize is only the first word. So you can reopen the string class if you want. This sounds like a good idea, right? And redefine the capitalize method, that is you monkey patch it. And this works fantastically well in your movie title class. You can see that it takes the string, the matrix there, all in lower case and capitalizes each word of it. Unfortunately, you may have other portions of your apps such as this sentence class down here. That's assuming you still have the original implementation of capitalize, which capitalizes only the first letter. Doesn't work so good for sentences. It's situations like this that refinements were created for. So you can take your monkey patch from the string class and convert it to a refinement. I won't go into details on all the syntax of refinements. Just Google Ruby refinements and you'll find several excellent tutorials. But basically, this is a refinement of the string class here. A refinement is basically a module that pre-pins an existing class, but only within lexical scopes that's files, classes, or modules that explicitly activate it. It's a bit of a mouthful, so let's just see what it does in action. Now that your refinement is defined, you can activate it within the movie title class. That'll override the capitalize method but only within movie title. Outside of the movie title in lexical scopes where we haven't explicitly activated the refinement, we still get the original version of capitalize and only the first letter of our string gets capitalized. So now the version of capitalize you get depends on your starting point where the method is called. In a scope where refinements haven't been activated, the sentence class, for example, it proceeds to the capitalize method on the string class, the original version, and invokes that. But in a lexical scope where the refinement has been activated, movie title, prepends the refinement module to the string class and that's the version of capitalize that Ruby encounters first, that's the version it'll invoke and we get each word capitalized. All right, one more time back to the terminal to play around with refinements. So here we've got a class and a refinement of that class and on my class we'll define my method which will simply print the name of that class, we'll then override that method within the refinement. So we print my refinement and then call super because since refinements are just a module, super works just like you're used to. We'll create a new instance of my class and call my method and then we'll activate the refinements and call my method again. All works fantastically well. We'll also put in a couple of markers so that we can tell whether the refinements are active or not. Okay, so now we'll drop back to the shell and invoke it and you can see that without refinements active, we get just my class all by itself. But after we activate the refinements with using my refinement, we get my refinement first and then super invokes my method on my class. All right, just about done. I wanna recap everything we've covered real quick. We'll have a few minutes for questions. I wanna thank a few folks who have helped out with this talk and then I've got a few resources you can go to to learn more. So to recap, you can call the ancestors method on any Ruby class to get a list of its ancestors. Every Ruby object has a singleton class that Ruby will look on for methods first. If a class inherits from a super class that gets added to the ancestors chain right after the class, if you include a module in the class that will add the module to the ancestors chain between the class and its ancestors. And if you prepend a module, that will add that module to the lookup chain prior to the class allowing you to override methods. If you have a refinement that in lexical scopes where it's added that gets prepended to the ancestors chain before the class it refines. You can define methods anywhere along this chain that you want. Ruby always starts its search for those methods at the singleton class and then proceeds along the chain looking for those methods as soon as it finds a method, it'll invoke it. If a method's defined at more than one point along the chain, Ruby will stop when it finds the first occurrence of that method and invoke that. And that's how method overriding is implemented. All right, that's all I have. So what questions do you have? Yes? Yes, cool. Okay, so the question is if you include two modules in a class, the one that you include second comes before the one that you included first. I believe I'm quoting you correctly there. Do I know the reason for that? I'm afraid that I don't. And that's why I advocate using ancestors to confirm what order methods will get called in. What happens if you define a singleton class, if you have a singleton class, you get a singleton class of that and define a method on that. Does it still proceed up the chain? I'm not even sure what the code would look like for that exactly. I'm not sure that singleton class is a method you can invoke on a singleton class. That, okay, I'm hearing back there that the singleton method lookup chain can recurse and it gets really messy, which I totally believe. So, okay, folks, we've got people watching the video at home that can't ask questions. Please ask on their behalf. Yes, that is a weird syntax thing. Okay, so the question is, if you go class less than, less than self, right? Do I have that syntax right? Then, yes, you can define methods within that scope. They do wind up on the singleton class for that object. And I can't remember what the official name for that syntax is. I believe, yes, okay, the question is, is there a difference between class and, so the question is, is there a difference between class shuffle, which is those two less than symbols, right? Oh, shovel operator, yes, sorry. Is there a difference between the class shovel self syntax and def self dot method? The end result is exactly the same. I can tell you that. Whether Ruby treats them differently, I'm not sure. I have, in the references section, I mentioned Ruby under a microscope. The answers you need would be there. I almost guarantee. All right, go in once, go in twice. All right, thanks to a few folks who helped out with this presentation. Avdi Grimm, right up here, did a technical review on it. Thanks very much. Thanks also to Pat Shaughnessy, author of Ruby under a microscope, and to James Adam, who did a talk earlier today on refinements for lots and lots of info regarding refinements. Thanks also to these Wikimedia users and OpenClipArt users for our work that got used in the course of the presentation. And now here are those helpful resources I promised you. Great place to start is the well-grounded Rubyist by David Allen Black. It starts out with singleton classes, moves on to modules. Basically, everything you wanna know regarding method lookup is covered in there. It's a fantastic resource. If you wanna go even deeper, look up Ruby under a microscope by Pat Shaughnessy. Basically, that's a tour of the Ruby language from the perspective of its C source code. Once you understand that, you will fully understand Ruby, believe me. And finally, I wanna mention the Ruby Tapas episode on refinements, also by Avdi. He made it freely available. It's a fantastic guide to refinements in general. Also, once James Adams, he just recorded it earlier today, so I didn't get a chance to include it in the slides. But James Adams' talk on refinements once that hits confreaks, another fantastic resource regarding refinements. Quick plug, if you wanna get your friends hooked on Ruby, find me, our head first Ruby is a great resource for you. Find me during Ruby comp. I have little cards with discount codes on the book. I also have a few up here at the podium. That's all I got. Thank you very much, folks.