Ruby Exception Handling

Self in Ruby: A Comprehensive Overview

For a variety of programming languages, the self (or this) keyword is a powerful tool, allowing developers to contextually refer to a particular class or object. This capability to refer to the current object, no matter the context, can be difficult to fully grasp, regardless of the language, and Ruby is no different.

In this article we’ll explore exactly what the self keyword is within Ruby and the various methods in which it is commonly used, so you’ll have a better understanding of how Ruby (and other object-oriented programming languages) handle self-referential keywords. Let’s get crackin’!

Contexts of Self

The purpose (and thus behavior) of self within Ruby is dependant on the situation, or the context in which the self keyword is used. In other words, within one context a call to self may refer to the parent class, whereas in a different context, self may refer to a particular instance of a class. To better illustrate the various contexts, we’ll outline each and provide code examples as well.

No matter which context the code finds itself, one important rule about self must be remembered: self always refers to one and only one object at any given time. The trick is to understand (and thus plan around) which particular object that will is, given the current context. Properly doing so provides a great deal of additional development power over the course of most any Ruby project.

Top Level Self

Top level context is for any Ruby code that is not executing inside any class, module, method, or otherwise any sub-level code block. Typically, top level code is just naked code in an .rb file, executed as a simple script or part of a larger application, without the need for object-oriented components.

For example, here is a very simple script that consists of four lines: creating a name variable at the top level of execution, then outputting three lines to the console to display both our name value and show us what self is.

The output is:

What’s critical here is that Ruby has told us that self, at least within the top level context, is an object called main. This is because all execution within Ruby occurs within the context of an object. When working inside a particular class, it’s obvious that that parent class is the object of that context, but when Ruby first begins execution, it automatically creates the main object. Thus, our call to self above refers to the main object instance that Ruby generates for us.

Class Definition Self

When defining a class within Ruby, we can also then refer to self within that context as well. Here we have an Author class, inside which we’re outputting the value of self:

The result is that, directly inside the context of a class definition, self is equivalent to the parent class in which it was defined; Author, in this case. In fact, in this context, the keyword self can be thought of as a substitute for the actual class name. Instead of using self here, we could use Author, and Ruby would treat it the exact same:

Module Definition Self

The use of self inside a module definition is very similar to that of a class definition. In fact, as far as Ruby is concerned, the reference to self doesn’t care whether you’re in the context of a class, or a module, it will treat both basically the same.

For example, here we’re enclosed our Author class inside the Library module, then output the value of selfwithin both contexts:

While Ruby treats the module definition call to self just as it did with the class definition, representing the parent level object of Library in this case, for the child call it recognizes that there’s a hierarchy here, so we get the module plus the class:

Class Method Self

We won’t get into the full details of what distinguishes a class method from an class instance method in this article, but the simple answer is:

  • A class method is a method that refers only to that class in all contexts, but not to any individual instances of that class.
  • A class instance method is a method that applies to all instances of that class, but not for the class object itself.

So, for our example of self, we’ve added the name class method to our Author class (defined by the self.object that precedes the definition). We’ve also added a @@name class variable, which isn’t necessary for this example, but is a more common practice since it allows our name method to act as a property getter method for the @@name value:

The fact that self.name is used to define a class method is a bit of a give away, but sure enough, self inside a class method definition refers to that parent class object — Author in this case. We also call Author.name in the output, to show that our class method getter behaves as expected:

Class Instance Method Self

As discussed in the previous section, a class instance method is a method that can be referenced by all instances of that class, but not directly by the class object itself. In Ruby, defining a class instance method is as simple as excluding the self. object prefix within the method definition; in this case, using just def name does the trick:

Since this is an instance method, we can’t call it until we create a new instance of our Author class. After that, once we call the name method on that instance, we get the full output. Unlike a direct class method reference to self, a class instance method reference to self actually points to the particular instance that is being executed, thus our output shows an instance of the Author class, as indicated by its memory address:

Class Singleton Method Self

The final context you’re likely to use self within is the class singleton method. A singleton method is a method that is attached to only one specific instance of an object — it cannot be called by any other instances of that object, nor directly by the class object itself.

To illustrate this, we’ve got our Author class again, but we haven’t created any methods directly within the Authorclass definition. Instead, we create a new instance called author, then define a singleton method by using the def [INSTANCE].[METHOD] syntax, or def author.name in our case:

Not only are we outputting the self values within our singleton method, but we’re also generating a second instance of our Author class (new_author), which we use to confirm that the name method is, in fact, a singleton method only associated with our original author instance of the class. The full output, once again, shows that inside the singleton method itself, self refers to that particular instance of the class: