Self Exploration: Self in Ruby Class and Instance Methods
Tags: ruby, beginners, codenewbie, tutorial
Published: 2022-12-07 04:28:08

In learning Ruby and Active Record over the past couple weeks, I found `self` one of the most useful yet also most potentially confusing tools in the language. Figuring out how to correctly use `self` can become especially tricky depending on whether you're writing class methods or instance methods—so in this post, we'll walk through how `self` works in each situation.

###Knowing Thine Self
First off, it helps to know what `self` is in general. In Ruby, `self` is a keyword that can refer to different things depending on the **context** in which you use it. Calling `self` returns the **current object**—but what that object is, _i.e._ the **value** of `self`, varies. This is exactly why it can be hard to keep track of what `self` means in any given situation.

For our purposes, we'll focus on how to use `self` in class and instance methods, and how it behaves differently in each. Also, while we'll look at Active Record model classes as examples here, the specific behavior of `self` and the overall concepts are applicable to Ruby classes in general.

_**Note:** Remember that by convention, documentation and other writing about Ruby differentiates class and instance methods by representing them with different punctuation. Class methods are referred to as they actually appear when invoked in code, with dot notation: `ClassName.class_method_name`. However, instance methods are shown with an octothorpe `#` in place of the dot: `instance_name#instance_method_name`. Just remember that in actual code they're both invoked with dot notation._ 

###Self in Instance Methods
Let's begin with instance methods, where `self` is the most straightforward. Say we have a class (in this case, an Active Record model) like this:

```Ruby
class Dingus < ActiveRecord::Base
  has_many :things

  def count_things
    self.things.size
  end
end
```
Our instance method `#count_things` returns the number of things that belong to the instance of `Dingus` **on which we call `#count_things`**. That last part is key: because `#count_things` is an instance method, we'll always call it on a particular instance of the `Dingus` class—and that specific instance is what `self` refers to in the context of the method.

Thus if `Dingus` instance `d1` happens to have 10 `Thing` instances associated with it, and `Dingus` instance `d2` has 20, the return values of `d1.count_things` and `d2.count_things` will be 10 and 20, respectively.

In instance methods, the `self` keyword is extremely useful. The example above only illustrates it in terms of basic Active Record association functionality, but it enables you to access any attribute of the instance, as well as any other instance methods the class has, inside the execution context of an instance method.

###Self in Class Methods
Class methods are where `self` tends to become more potentially confusing. First of all, the keyword **must be used in the definition of a class method**, like this one added to our `Dingus` class:

```Ruby
class Dingus < ActiveRecord::Base
  has_many :things

  def count_things
    self.things.size
  end

  def self.has_most
    self.all.sort_by {|dingus| dingus.count_things}.last
  end
end
```
This class method `.has_most` iterates over every instance of the `Dingus` class and sorts them in order of how many `Thing`s they have by calling `#count_things` on each one. Finally, it returns the last instance of `Dingus` from that sorted collection, which will be the one with the most `Thing` instances because the sort order is ascending by default.

We can immediately tell `.has_most` is a class method because it has `self` in the definition. This is simply the necessary syntax to define a class method, but it also makes sense: in the execution context of the class, `self` refers to the class itself.

Moreover, within the class method, `self` **still refers to the class**, not any particular instance thereof. Thus, in this class method, `self.all` is equivalent to `Dingus.all`.

###TLDR
Most simply put, just remember: _Inside instance methods, `self` refers to the specific instance the method is called on._

Meanwhile, `self` is _used in the definition of class methods_, **and** _inside class methods, `self` refers to the class itself_, not any particular instance.

Keep these distinctions in mind, and it'll be much clearer when and how to use `self` in different situations.