#---Self---
The self
keyword in Ruby refers to the current object.
So its value changes depending on where it is used.
It’s kinda like the this keyword in JavaScript.
class Dog
def self.who_am_i
self
end
def who_am_i
self
end
end
The self inside any class method refers to the class itself:
p Dog.who_am_i # => Dog
But the self inside any instance method refers to the specific instance of the class:
p Dog.new.who_am_i # => #<Dog:0x00007f8c1c0b2a20>
The self inside a class body, like this, also refers to the class itself:
class Dog
p self
end
The self inside a module’s method depends on how the module is used:
module Trainable
def trainable_who_am_i
self
end
end
If the module is included in a class, then self will refer to the instance of that class:
class Dog
include Trainable
end
p Dog.new.trainable_who_am_i # #<Dog:0x00007f8c1c0b2a20>
But if it is extended, then self will refer to the class itself, not its object:
class Cat
extend Trainable
end
p Cat.trainable_who_am_i # Cat
What about self outside of a class, module or a method?
self, here, refers to the main
object in Ruby. It’s
a special object that belongs to the Object
class:
p self # => main
p self.class # => Object
When you call a method or a function, you’re always calling it on an object:
## Here, `new` is called on the `Dog` class
p Dog.new
## `who_am_i` is called on the `Dog` instance
p Dog.new.who_am_i # => #<Dog:0x00007f8c1c0b2a20>
But there are times when you’ll come across a function that’s called without an explicit receiver. Like here:
class Dog
def name
"Pongo"
end
def speak
## Here, `name` is called without an explicit receiver
"Woof! My name is #{name}."
end
end
Or, like our friends p
and puts
, which are always
called without an explicit receiver:
p "Hello"
puts "World"
In these cases, despite not having an explicit receiver, these method are still called on certain objects. Which ones? The ones referenced by self at that point in the code.
In the speak method above, name is called on the
instance of the Dog
class.
In the p and puts methods above, they are called on
the main object discussed earlier.
self
:class Calculator
def initialize
@value = 0
end
def add(n)
@value += n
self # returns the calculator instance
end
def subtract(n)
@value -= n
self
end
def result
@value
end
end
calc = Calculator.new
p calc.add(5).subtract(3).add(2).result # => 4
The Rails gem ActiveRecord implements method chaining.
class Dog
attr_accessor :name
def update_name(new_name)
## With self, this calls the setter method correctly
self.name = new_name.upcase
## Without self, this creates a local variable.
## Comment the above and uncomment the below to see:
## name = new_name.upcase
end
end
d = Dog.new
d.update_name("pongo")
p d.name # => "PONGO"
#