In Ruby,
attr_accessor is a macro (or method) for automatically creating a getter (method to access the value) and a setter (method to set the value) for instance variables in a class.
For example:
class Cat
end
cat = Cat.new
cat.name # => no method error
We do not have a
name method in the
Cat class. Obviously, we get a no method error.
Let's try to add a getter:
class Cat
def name
@name # returns the instance variable @name
end
end
cat = Cat.new
cat.name # => nil
It seems something went wrong. But everything is correct. The getter cat.name returns nil. There is no longer a 'no method error', meaning the method exists and returns the instance variable @name of the Cat instance. But this variable is empty. nil is the expected result.
In Ruby, a
getter is a method that allows you to get the value of an instance variable in a class. Getters are called so because they allow you to "get" (
get) the value of a variable.
In Ruby, getters are typically used to provide access to variable values from outside the class, as variables are usually private and not directly accessible. Getters allow controlled access to these values.
Trying to use a setter results in a no method error:
cat.name = 'Ruby'# => no method error
This is also an expected result. We do not have a setter method for name.
In Ruby, a setter is a method that allows you to set the value of an instance variable in a class. Setters are called so because they allow you to "set" (
set) (or change existing) values of a variable.
In Ruby, setters are used for controlled modification of variable values from outside the class.
class Cat
def name
@name # returns the instance variable @name
end
def name=(str)
@name = str
end
end
Let's create a Cat instance and call the name method (getter):
cat = Cat.new
cat.name # => nil
Everything is correct here. Our instance is currently empty. We need to pass a value using our new method (setter).
cat.name = 'Ruby'
We do not see any errors. So let's try to retrieve the value using the getter method:
cat.name # => Ruby
Everything works. But imagine that your class has not just name, but dozens of different attributes (age, color, etc.). Writing getter and setter methods every time is not very convenient.
So in Ruby, there are shortcuts (attr_reader and attr_writer):
class Cat
attr_reader :name
attr_writer :name
end
:name - the name of the attribute for which the method is created.
attr_reader is a shortcut for the getter method:
def name
@name # returns the instance variable @name
end
attr_writer is a shortcut for the setter method:
def name=(str)
@name = str
end
But when we need both methods - setter and getter, attr_reader and attr_writer need to be duplicated for each attribute:
class Cat
attr_reader :name
attr_writer :name
attr_reader :color
attr_writer :color
end
This is more concise than writing the methods fully, but Ruby allows you to shorten this code as well. Here we need
attr_accessor.
class Cat
attr_accessor :name
attr_accessor :color
end
This is equivalent to writing:
class Cat
attr_reader :name
attr_writer :name
attr_reader :color
attr_writer :color
end
Using
attr_accessor, attr_reader, and attr_writer simplifies the creation of access methods for variables in classes, and it is especially convenient when you only need to simply get or set a variable's value without additional logic.
Ruby allows you to shorten what seems already shortened. Here is a version of the shortened attribute declaration separated by commas:
attr_reader :name, :color