Ruby and self

What’s self?

Ruby newcomers usually are confused about the use of self, whether it’s a completely new concept for them or not.

First, let’s define self:

self is the current object

The definition may seem a little too dry, but that’s exactly what self is. In your code, at any time, there’s always a self object, and its value depends on the code context.

IRB and self

When practicing with ruby, irb is your best friend. For those who want to get fancy you can replace it with pry. Let’s see some examples, first start the irb session with the irb command, then let’s see what irb has to say about self:

$ irb

2.1.0 :001 > self
 => main 

> self.inspect
 => "main" 

self.class
 => Object 

There’s always a self when executing ruby code: at startup irb creates a top level object called main, which is actually just an instance of the Object class. That’s your default self.

self at class definition

Time to move on. Let’s see what self is when defining a class:

class Person
  self
end

 => Person

It’s the class itself, and it makes perfect sense. Do you know about class methods? When you’re out of the context of the class, you can define them like this:

def Person.show_self
  self.inspect
end

Person.show_self
 => "Person" 

But when you’re in the context of the class, you can define class methods in both these ways:

class Person
def Person.show_self
self.inspect
end
def self.show_self self.inspect end end Person.show_self => "Person"

They are equivalent, but the latter is preferable. Why? Because if you decide to change the name of the class, you don’t have to change the name in the signature method as well. 

self in instance methods

What about instance methods? Inside instance method definitions, self is the actual instance:

class Person
  def show_self
    self.inspect
  end
end

Person.new.show_self
 => #<Person:0x00000101939098>

Most of the times, inside method body definitions, self is redundant and we can avoid it:

class Person
  def self.show_self # class method, self is the class
    inspect
  end

  def show_self # instance method, self is the instance
    inspect
  end
end
Person.show_self
 => "Person"

Person.new.show_self
 => #<Person:0x00000101939098>

When self is required

There are some cases when you need an explicit self, namely when inside the method body there’s a local variable with the same name of the method you’re willing to call on self. If you omit self you’re going get some unexpected results for sure:

class Person
  def show_self
    inspect = 'boo!'
    inspect
  end
end

Person.new.show_self
 => "boo!"

class Person
  def show_self
    inspect = 'boo!'
    self.inspect
  end
end

Person.new.show_self
 => #<Person:0x00000101939098>

Another very common scenario when self is always required is when using writer methods:

class Person
  attr_accessor :name

  def set_name(person_name)
    self.name = person_name
  end
end

me = Person.new
me.set_name 'Andrea'

me.name
 => "Andrea"

If we had written

def set_name(person_name)
  name = person_name
end

then the code would have created a local variable named name.

The last important case when self is required is when you call the class method of an instance:

class Person
  def show_class
    self.class
  end
end

Person.new.show_class 
 => Person

In this case self is required because class is a reserved keyword, so we need to make sure the parser undestands we’re referencing to the instance class object.

When self cannot be used

Sometimes on the other hand you cannot use the explicit self: that’s the case with private methods:

class Person
  attr_accessor :name

  private :name

  def show_name
    name
  end

  def buggy_show_name
    self.name
  end
end

me.show_name 
 => "Andrea"

me.name
 NoMethodError: private method `name' called for #<Person:0x00000101939098& @name="Andrea">

me.buggy_show_name
 NoMethodError: private method `name' called for #<Person:0x00000101939098& @name="Andrea">

Wrapping up

In order to write idiomatic ruby, the rule of thumb is to avoid the explicit self whenever it’s not required.

Leave a Reply

wpDiscuz