Exploring Self
Tags: ruby, codenewbie, webdev, beginners
Published: 2019-10-08 15:56:11

As many of you know, I have recently become a software engineering coach for the bootcamp I attended. While going through our first module it appeared that a lot of our students had a tough time grasping the concept of `self`. At first, I fumbled around with explaining it in the simplest words. This really woke me up because I pride myself on writing blog posts in simple terms that are easy for beginners to understand.

I know with great thought, I can explain things in a simple way, but on the spot, I struggle. I want to get better at this and to accomplish this, it means I need to gain a deeper understanding of the topic. So, here I am writing this lovely blog post on the concept of `self` in Ruby. 

Let's get started. 

### What is self?

In Ruby, `self` is a tool that allows developers to refer to a particular object or class. Grasping the concept of `self` could be difficult because the object or class that `self` refers to changes.  The way `self` changes is reliant upon the context in which it is being called in.  

There are many different contexts in which `self` can appear and I am going to do my best to cover as many as I can think of. Forgive me if I leave one or two out. If you know of a few others and want to include them in the comments below to add to the discussion, please do so!

### Top Level Self Context

Outside of any Ruby class, method, module, etc. `self` refers to the top level, which is an object called `main`. This `main` object exists in an empty `.rb` file. Ruby is an object oriented language, so even within an empty `.rb` there is an object! Pretty cool, huh?! 
 
![Top Level Self Code Snippet](https://thepracticaldev.s3.amazonaws.com/i/yk7zeiklopfvxvjx2dsa.png)

### Module Self Context

Within a `module`, the context of `self` refers to the `module`. If it helps, you could think of `self` in this context as just referring to the name of the `module`. So, if we have a `Pet module` and we called `self` it would output `Pet`. 

![Module Level Self Code Snippet](https://thepracticaldev.s3.amazonaws.com/i/d6cjhu4fct9w8uiye8vz.png)

### Class Self Context

The context of `self` in a `class` is very similar to that of a `module`. `self` refers to the class that it is in and can also be a substitute of the `class` name itself. So, if we have a `Dog class` and we called `self` it would output `Dog`. 

![Class Level Self Code Snippet](https://thepracticaldev.s3.amazonaws.com/i/mul1mwktyw7kpgq701si.png)

Seems pretty simple, right? Well, at this point, it is! It's in the next two contexts that things seem to get a little confusing. 

### Class Method Self Context

This is where things start to get a little tricky and harder to grasp. Hopefully you have an idea of what a class method looks like. If not, it is a method that has `self.` prepended to the method name. In the context of `class` methods, `self` points to the `class` itself. It does not point to the instance of a `class`, but to the `class` as a whole. 

For a simple example, let's say we have a `class` variable called `@@name` and we wanted to be able to *get* it outside of the class. In order to accomplish this, we need a `class` method.

![Simple Class Method Example](https://thepracticaldev.s3.amazonaws.com/i/fyom7s13adsyro6xv925.png)

In `self.name`, I used `puts self` to retrieve what `self` is pointing to within this `class` method. If you noticed, it's pointing to the `Dog class` not an instance of it. 

The way we call `class` methods is by using the `class` name, in our case it is `Dog`, followed by the name of the method. So, if we called `Dog.name` outside of the `class` the output would be `Buddy`. 

#### Diving Deeper

Alright, so, let's dive in and think about this `Dog class` in a broader way. Let's say a dog is having puppies. Each new puppy that is born is a new instance of the `Dog class`. So if a dog has 4 puppies, there would be 4 new instances of the `Dog class`. 

Well, as great dog owners, we want to keep track of all the dogs we have by creating an `@@all` variable which we'll set to an empty array. Each time that one of the puppies is born, we pass the new instance of the `Dog class` that is created into this `@@all` variable. This way, we have all of the dogs in one place! (I'll dive into more context on how and where this should happen later.)

If we want to return this array of all of our dogs, we must create another one of those handy `class` methods to *get* the array. 

![@@all Class Method Code Snippet](https://thepracticaldev.s3.amazonaws.com/i/u6hgc52makir3lhnpr7u.png)

If we called `Dog.all` it would return the array of all instances of the `Dog Class` that have been created, which means `self` is pointing to the `class` itself and not an instance of the `class`.  

### Class Instance Method Self Context 

You know how before I mentioned we'd discuss where and how we'd add each new instance of the `Dog class` to the `@@all` array? Well, here we go!

#### `initialize`

In this case, we want to create an `initialize` method which is called on any time a new instance of a `class` is created. Our `initialize` method takes a `:name` and `:breed` and also adds this new instance to the `@@all` variable by calling `self`. 

Let's pause for a second. Thinking about everything I just said, what do you think `self` will refer to when called in the `initialize` method? 

If you guessed that `self` points back to the new instance of the `class` being created, you are correct!

![Intialize Method Code Snippet](https://thepracticaldev.s3.amazonaws.com/i/qfeo6tz10eevb0z9ansq.png)

To make sense of this, within the `initialize` method we are setting instance variables to be used throughout the class using the parameters given. Unlike our previous example with `@@name`, the name `"Buddy"` will only refer to that instance of the `Dog class`, as not all dogs created are named `"Buddy"`. If you think about it, if we are assigning these variables for this specific instance of the `class` in this method then `self` must be pointing to the instance of the `class`. 

#### All Other Class Instance Methods

`initialize` is not our only class instance method. Any method you create within a `class` which is not prepended by `self.` is an instance method. This means that in any of those methods `self` refers to the instance of the class it is being called on. 

![Class Instance Methods Code Snippet](https://thepracticaldev.s3.amazonaws.com/i/0xaordmf89di0euju14y.png)

This is why we use `buddy.play_fetch` instead of `Dog.play_fetch`. We want Buddy, the black lab, to play fetch with a stranger not the `Dog class`. 

### Final Thoughts

We've explored a few different contexts of `self` in Ruby today. We've learned that within a blank `.rb` file, `self` refers to the `main` object. We now know that within a `class` and `module`, `self` refers to the `class` or `model` it is in, unless of course we are calling it within an instance method in a class, in which case it points to the instance of the `class`. Finally, we learned about `class` methods and that they refer to the `class` itself.  

Hopefully, if you were having trouble understanding the concept of `self`, you have a better understanding of it now thanks to all the puppies.

Happy Coding!

*Note: The cover image for this blog post is brought to you from the Sunflower Festival at Swank Farms in Hollister, CA.*

#### Sources
[Self in Ruby: A Comprehensive Overview](https://airbrake.io/blog/ruby/self-ruby-overview)
[@/@@ vs. self in Ruby](https://medium.com/@sgg2123/vs-self-in-ruby-1d4d88170)