DEV Community

Martin Souza
Martin Souza

Posted on • Edited on

Self Exploration: Self in Ruby Class and Instance Methods

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:

class Dingus < ActiveRecord::Base
  has_many :things

  def count_things
    self.things.size
  end
end
Enter fullscreen mode Exit fullscreen mode

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:

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
Enter fullscreen mode Exit fullscreen mode

This class method .has_most iterates over every instance of the Dingus class and sorts them in order of how many Things 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.

Top comments (1)

Collapse
 
naucode profile image
Al - Naucode

Hey, it was a nice read, you got my follow, keep writing!