How to Use the Ruby "Self" Keyword

How to use Ruby's self keyword

In most cases self.foo is indeed redundant because you can just write foo for the same effect, but in this case it is not and the self is required.

var_one = method(args) will create a local variable called var_one, it will not call any method or do anything else to self.

self.var_one = method(args) will call the method var_one= on self with the argument method(args).

Another case where the use of self is non-optional would be if you want to pass it as an argument to a method, i.e. some_method(self) - you can't do that without the self keyword.

How to use the Ruby self keyword

Usually, self as a receiver can be omitted, and in such cases, it is usually preferable to do so. However, there are a few cases when omitting self make the code mean something else.

  • One such case is, as in your example self.name = ..., using a setter method. Ruby's syntax is ambiguous between method and variable call, and when something that can be interpreted either as a variable or a method is followed by =, its interpretation as a local variable assignment has priority.

  • Another case is when you want to call the method class. There is also the keyword class, and interpretation of class as the keyword has priority over it as the method.

  • Still another case is when you want to use the method []. This notation is also used for array literal, and interpretation of it as an array has priority over it as a method.

In each of these cases, you have to make the expression be unamgiguously a method call. One way is to explicitly write the receiver even when it is self. The other way is to write () after the method.

Regarding your example self.each_with_index ..., the self can be omitted, and not doing so is not a recommended practice.

What is the 'self' keyword doing exactly in this Class method?

self is the class Restaurant. def self.method is how you implement a method on the class itself rather than an instance of the class. Restaurant.filter_by_city(...) rather than Restaurant.new.filter_by_city(...).

self changes in Ruby depending on context. Within a method, self is the object the method was called on.

Within the class Restaurant block, and outside of any method, self is the Restaurant object which is a Class object. Everything is an object in Ruby. Everything.

You can also do this by declaring a block where the class is the instance.

class << self
def filter_by_city(restaurants, city)
restaurants.select { |restaurant| restaurant.city == city }
end
end

Normally you'd use this syntax if you have a lot of class methods.

See Self in Ruby: A Comprehensive Overview for more.

When to use self in module's methods

Use self in each method definition if you want the methods to be defined only in the singleton class of the module (where the methods defined using self live). Omit self and extend self if you want the methods of the module to be defined as instance methods and singleton methods at the same time.

For instance, you can call the method using RG::Stats.sum(array) and still have it listed by the instance_methods method if you do this:

module RG::Stats
extend self

def sum(a, args = {})
a.inject(0){ |accum, i| accum + i }
end
end

This way, the sum method is defined as an instance method and it is included in the singleton class of the module after using extend self.

You can check the instance methods of RG::Stats module to verify this:

RG::Stats.instance_methods
=> [:sum]

With this technique you don't have to worry about defining the method without the self keyword because modules can't have instances so it cannot be called like an instance method of RG::Stats module. It can only be called as a singleton method RG::Stats.sum(array) thanks to the extend self statement.

Understanding the self keyword when referring to a class instance variable in a ruby?

tl;dr: foo = value will always refer to a local variable foo not the method call self.foo=(value).


I am assumed this is because I need the self keyword to refer to the instance variable, total

No, total is a local variable, not an instance variable. @total is an instance variable. A local variable lives for the current scope, like a single method call. An instance variable sticks with the object.

You need the self keyword to refer to the method total=. Let's dive in.

attr_accessor :total declares two methods, total and total=. These are wrappers to get and set the instance variable @total. The following code does the equivalent.

def total
@total
end

def total=(value)
@total = value
end

Note that the method is named total=, this will become important in a moment.

With that in mind, let's look at your code.

def add(amount)
self.total = self.total + amount
end

(Almost) everything in Ruby is really a method call. The above is syntax sugar for calling the total= method on self.

def add(amount)
self.total=(self.total + amount)
end

Now what happens if we remove self like so?

def add(amount)
total = total + amount
end

In Ruby, self is optional. Ruby will figure out if total means the method total or the local variable total. The local variable takes precedence and assignment is always to a local variable.

total = total + amount works like so:

def add(amount)
total = self.total + amount
end

Assignment is always to a local variable.

To further illustrate, what if we declared total first?

def add(amount)
total = 23
self.total = total + amount
end

The existing local variable total takes precedence over the total() method. total + amount refers to the local variable total and so cr.add(10); puts cr.total will be 33.


total = ... will always refer to the local variable total. For this reason if you want to use method assignment you must explicitly use self.total=. In other cases you can drop the self. And avoid local variables with the same name as methods.

def add(amount)
# self.total = self.total + amount
self.total = total + amount
end

Why did I not need self in add_student?

Because there is no ambiguity. You're not assigning to a local variable roster.

def add_student(student, grade)
roster[grade] = roster[grade] || []
roster[grade] << student
end

roster[grade] is really self.roster.[]=(grade). You are calling self.roster which returns a Hash and then calling the []= method on that Hash to give it a new key/value pair.

Similarly, roster[grade] << student is self.roster.[](grade).<<(student). Get aHash, call [[]](https://ruby-doc.org/core/Hash.html#method-i-5B-5D) on it to retrieve theArrayand call [<<](https://ruby-doc.org/core/Array.html#method-i-3C-3C) on thatArray`.

def add_student(student, grade)
self.roster.[]=(grade) = self.roster.[](grade) || []
self.roster.[](grade).<<(student)
end

Yes, [], []=, and << are all methods names like any other.


A lot of Ruby mysteries go away once you understand the method calls under the syntax sugar and that things like [], []=, << and so on are method names.

Scope and the 'self' keyword

Inside method self is an instance of Temperature. Inside class it is an instance of Class, having a name Temperature.

Try this:

class Temperature
puts "Inside class: self is #{self}, Temperature is #{Temperature}"

def meth
puts "Inside method: self is #{self}, Temperature is #{Temperature}"
end
end

Temperature.new.meth

That said, inside class, those are equivalent:

class Temperature
def self.meth ; end
def Temperature.meth ; end
end

But inside method, self becomes in instance variable, while the constant Temperature, instance of Class, still refers to what you expected.

To refer it’s class from inside instance method, one might use self.class. That said, inside instance method, those are equivalent:

class Temperature
def meth
Temperature.ctof(...)
self.class.ctof(...)
end
end

What does self mean in Ruby?

self refers to the object that is currently in context.

In your example, self is the class itself and def self.method is defining a class method. For example:

class MyClass
def self.method
puts "Hello!"
end
end

> MyClass.method
#=> "Hello"

You can also use self on instances of a class.

class MyClass
def method_a
puts "Hello!"
end

def method_b
self.method_a
end
end

> m = MyClass.new
> m.method_b
#=> "Hello!"

In this case, self refers to the instance of MyClass.

There is a good blog post on self in Ruby here, or, as it was pointed out in the comments, there is some more on this in the Ruby documentation.



Related Topics



Leave a reply



Submit