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 keywordclass
, and interpretation ofclass
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 a
Hash, call [
[]](https://ruby-doc.org/core/Hash.html#method-i-5B-5D) on it to retrieve the
Arrayand call [
<<](https://ruby-doc.org/core/Array.html#method-i-3C-3C) on that
Array`.
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
Change HTML Form Id Generated by Form_For Rails 3.1
How to Detect Browser Type and Its Version
Carrierwave Fog Amazon S3 Images Not Displaying
Elasticsearch Terms Aggregation by Entire Field
Ending a Rails 2 Url with an Ip Address Causes Routing Error
Referencing Model with String Input
Difference Between String.Scan and String.Split
How to Set the Rails Environment for My Somewhat Stand Alone Ruby Script
How to Mock Aws Sdk (V2) with Rspec
Ruby on Rails User Registration Using Rest API Call and Devise
Ruby, Tor and Net::Http::Proxy
Error Installing Gem: Couldn't Reserve Space for Cygwin's Heap, Win32 Error 487
How to Enable Compression in Ruby on Rails
Accessing One Controller Variable in Another Controller in Rails
Can't Launch Simple Sinatra App Using Rackup and Jruby (No Response from Web Server)