Attr Accessor in Ruby
-
Create an Instance Variable
full_name
Using a Simple Class in Ruby -
Use the
attr_reader
to Read Multiple Instance Variables in Ruby -
Use the
attr_writer
to Write Multiple Instance Variables in Ruby -
Combine Both
attr_reader
andattr_writer
Intoattr_accessor
in Ruby
The attr_accessor
is a shortcut in Ruby OOP design for attr_reader
and attr_writer
.
Therefore, to understand attr_accessor
, you must first understand how attr_reader
and attr_writer
work. To illustrate how these work, we will create a simple class.
Create an Instance Variable full_name
Using a Simple Class in Ruby
class Employee
def initialize(last_name, first_name)
@full_name = "#{last_name} #{first_name}"
end
end
employee1 = Employee.new('John', 'Doe')
puts employee1.full_name
Output:
undefined method 'full_name' for #<Employee:0x0000558c7cbc9400 @full_name="John Doe"> (NoMethodError)
The simple Employee
class above has a constructor that accepts the employee’s last and first name and uses this to create an instance variable full_name
.
If we create an instance of this class and read the full_name
, we get a NoMethodError
error, as shown in the output above. We will need to create another method that returns the instance variable.
class Employee
def initialize(last_name, first_name)
@full_name = "#{last_name} #{first_name}"
end
attr_reader :full_name
end
employee1 = Employee.new('John', 'Doe')
puts employee1.full_name
Output:
John Doe
Use the attr_reader
to Read Multiple Instance Variables in Ruby
Does it mean if we have multiple instance variables that need to be read, we will have to create a method for each of them?
That would make our class unnecessarily long. As a result, Ruby provides us with attr_reader
to achieve this.
class Employee
attr_reader :full_name
def initialize(last_name, first_name)
@full_name = "#{last_name} #{first_name}"
end
end
employee1 = Employee.new('John', 'Doe')
puts employee1.full_name
Output:
John Doe
As you can see in the code above, we have the same output as the previous code. The addition of attr_reader :full_name
adds the full_name
method under the hood, allowing us to write a concise class.
Let’s assume that we also need to reset the instance variable. We might try something like this:
class Employee
attr_reader :full_name
def initialize(last_name, first_name)
@full_name = "#{last_name} #{first_name}"
end
end
employee1 = Employee.new('John', 'Doe')
# After doing some operation on employee1 and we need
# to rename the full name
employee1.full_name = 'Nicolas Daniel'
Output:
undefined method 'full_name=' for #<Employee:0x000055bc12240940 @full_name="John Doe"> (NoMethodError)
One way to do that is to define a full_name=
setter method that resets the instance variable.
class Employee
attr_accessor :full_name
def initialize(last_name, first_name)
@full_name = "#{last_name} #{first_name}"
end
end
employee1 = Employee.new('John', 'Doe')
# After doing some operation on employee1 and we need
# to rename the full name
employee1.full_name = 'Nicolas Daniel'
puts employee1.full_name
Output:
Nicolas Daniel
Use the attr_writer
to Write Multiple Instance Variables in Ruby
Instead of defining a separate setter method as we have done here, Ruby also provides us with the attr_writer
that can help us.
class Employee
attr_accessor :full_name
def initialize(last_name, first_name)
@full_name = "#{last_name} #{first_name}"
end
end
employee1 = Employee.new('John', 'Doe')
# After doing some operation on employee1 and we need
# to rename the full name
employee1.full_name = 'Nicolas Daniel'
puts employee1.full_name
Output:
Nicolas Daniel
As we can see in the output above, we have the same result with the addition of attr_writer
, even though we have removed the setter
method previously defined.
Combine Both attr_reader
and attr_writer
Into attr_accessor
in Ruby
Our final code is a lot better than defining getter and setter methods for every of our instance variables, but Ruby still allows us to move a step further by combining both attr_reader
and attr_writer
into attr_accessor
.
class Employee
attr_accessor :full_name
def initialize(last_name, first_name)
@full_name = "#{last_name} #{first_name}"
end
end
employee1 = Employee.new('John', 'Doe')
# After doing some operation on employee1 and we need
# to rename the full name
employee1.full_name = 'Nicolas Daniel'
puts employee1.full_name
Output:
Nicolas Daniel
As we can see above, with attr_accessor
, we automatically have a getter and a setter for an instance variable.