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
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
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.
Top comments (1)
Hey, it was a nice read, you got my follow, keep writing!