bootrails.com is now moving to saaslit.com  See you there!
bootrails moves to  saaslit.com
Post

Ruby, the self keyword

What is self in Ruby

self is a reserved keyword in Ruby that always refers to the current object and classes are also objects, but the object self refers to frequently changes based on the situation or context. So if you’re in an instance, self refers to the instance. If you’re in a class, self refers to that class.

self refers to the context

Yes, the context is where your code is at any given moment.

If your code is inside an instance method, self is an instance of that class. In other words, self is an object.

Let’s try that, and output self. In order to do that we need to add it somewhere inside the object. Any method would be good for that.

1
2
3
4
5
def name
  puts self 
end
name
# => main

This code defines and calls a .name method which prints the value of self.

self is initially set to main, an instance of the Object class that is automatically created whenever a Ruby program is interpreted.

The main object is the “top-level” namespace of the program.

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.

As seen here:

1
2
3
4
5
6
class Person
  def name
    puts self end
  end
Person.new.name 
#<Person:0x000056198a868c98>

From these examples, we can tell that the value of self changes depending on where you use it.

I believe you can understand anything better by understanding its purpose.

Let’s look at some examples.

Self, inside a Class definition

In a class definition (but not in an instance method), the self keyword refers to the class itself.

Here we have Person class, inside which we are outputting the value of self:

1
2
3
4
class Person
 puts self 
end
# => Person (the Person class)

The result is that, directly inside the context of a class definition, self is equivalent to the parent class in which it was defined; Person, in this case.

In singleton methods, the self keyword also refers to the class itself.

1
2
3
4
5
6
7
class Person
  def self.name
    puts self 
  end
end
Person.name
# => Person

Why we use self in method definition?

Let’s look at more common use case… Defining class methods !

Class-Level Methods

I’m sure you have seen it in above example. These def self.method_name method definitions.

Because we don’t have to use the class name for each method definition, making our code easier to change if we change the class.

That’s why we do def self.name instead of def Person.name.

Another more advanced way to do this is to define a method inside the Class instance itself.

This is referred to as the eigenclass or the singleton class and it uses the self keyword to open a new context where the Class instance is held in self.

Let’s check with an example.

1
2
3
4
5
6
7
8
9
class Person
  class << self
    def name
      puts "Jane"
    end
  end
end
Person.name 
# => "Jane"

Instance method : self

An instance method is a method that applies to all instances of that class, but not for 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:

1
2
3
4
5
6
7
8
9
10
11
12
13
class Person
  def name
    puts "self inside method is: #{self}"
    puts "self.class is: #{self.class}"
    return "Jane"
  end
end
# Define instance
person = Person.new
person.name
# => self inside method is: #<Person:0x000000010c38be10>
# => self.class is: Person
# => "Jane"

Since this is an instance method, we can’t call it until we create a new instance of our Person 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, an instance method reference to self actually points to the particular instance that is being executed, thus our output shows an instance of the Person class, as indicated by its memory address:

1
# => self inside method is: #<Person:0x000000010c38be10>

Self, inside a Module definition

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 are in the context of a class, or a module, it will treat both basically the same. For example, here we are enclosed our Person class inside the Type module, then output the value of selfwithin both contexts:

1
2
3
4
5
6
module Type
  puts "Self inside Type is: #{self}" 
  class Person
    puts "Self inside Type::Person is: #{self}" 
  end
end

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

1
2
Self inside Type is: Type
Self inside Type::Person is: Type::Person

How self work when it not use with instance variable and method

When a method is called without an explicit self, the implicit self is used, which is the value of the self keyword. In the following example, the Person#name method uses the value from Person#first_name and Person#last_name, but does not explicitly use self and relies on the value of the implicit self.

1
2
3
4
5
6
7
8
9
10
11
12
class Person

  attr_reader :first_name, :last_name
  
  def initialize(first_name, last_name) 
    @first_name = first_name @last_name = last_name
  end

  def name
    "#{first_name} #{last_name}"
  end 
end

Relying on the implicit self can save quite a bit of typing over time and is very common among Ruby programmers.

Summary

  • self is a keyword in Ruby representing the default object of the current context.
  • self is the default receiver of messages and the owner of instance variables.
  • Three rules for determining self: 1) when the current context is outside of any class/module/method definition, self is main; 2) when the current context is inside a class/module definition and outside of method definitions, self is the class/module; 3) when the current context is inside a method definition, self is the receiver of the method, the object before dot(.).
This post is licensed under CC BY 4.0 by the author.