Programming Ruby: Differences between attr_writer, attr_reader & attr_accessor
One of the most interesting thing about Ruby is the way it shares its instance variables by using keys like attr_writer, attr_reader and attr_accessor. Different accessors can be used to communicate intent to someone reading your code, make it easier to write classes and simplify repetitive code.
Here’s how Ruby’s accessors work:
If you write:
attr_writer :age
That gets translated into:
def age=(value)
@age = value
end
If you write:
attr_reader :age
That gets translated into:
def age
@age
end
If you write:
attr_accessor :age
That gets translated into:
def age=(value)
@age = value
enddef age
@age
…And that’s pretty much is what is happening in the background.
Another further example, integrating with a Ruby class. Let’s say you have a class Person:
class Person
endperson = Person.new
person.name # => no method error
Obviously we never defined method name. Let’s do that.
class Person
def name@name # simply returning an instance variable @nameend
endperson = Person.new
person.name # => nil
person.name = “Dennis” # => no method error
Aha, we can read the name, but that doesn’t mean we can assign the name. Those are two different methods. The former is called reader and latter is called writer. We didn’t create the writer yet so let’s do that.
class Person
def name
@name
enddef name=(str)
@name = strend
endperson = Person.new
person.name = ‘Dennis’
person.name # => “Dennis”
Awesome. Now we can write and read instance variable @name using reader and writer methods. Except, this is done so frequently, why waste time writing these methods every time? We can do it easier.
class Person
attr_reader :nameattr_writer :nameend#Even this can get repetitive. When you want both reader and writer #just use accessor!class Personattr_accessor :nameendperson = Person.newperson.name = “Dennis”person.name # => “Dennis”
Works the same way! And guess what: the instance variable @name in our person object will be set just like when we did it manually, so you can use it in other methods.
class Person
attr_accessor :namedef greeting“Hello #{@name}”endendperson = Person.newperson.name = “Dennis”person.greeting # => “Hello Dennis”
That’s it. In order to understand how attr_reader, attr_writer, and attr_accessor methods actually generate methods for you, read the Ruby docs.