What exactly is the difference between attr-accessor, attr_reader, and attr-writer?

Selam Degefu
3 min readJun 3, 2021

If you are like me, you probably had a hard time wrapping your head around the different macros in Ruby and when to use which. In this blog, I will go through each of them and explain when you should use them.

When we create class methods in ruby, by default the data in that class are private so when we try to manipulate the data or read it, we can’t do that. It’s very important we set our attributes to access them. To start being able to access the data, we set a method for it. Let’s see an example

class Person def initialize(name)
@name = name
end
def name
@name
end
end selam = Person.new("Selam")

In this example, since our name is something we don’t need to edit or “set” we can define it without using the name=(name) method. This is called a getter. Let’s say the Person class wants to add an attribute like age, since this is something that changes every year, we would say this is a setter. Anything that has = next to the method would be a setter.

class Persondef initialize(name)
@name = name
@age = age
enddef name
@name
end
def age=(age)
@age
end
endselam = Person.new("Selam")

However, this can get a bit lengthy and goes against Ruby’s love for creating efficient code. The other benefit of using macros at the top of the class is being able to see which ones have getter and/or setter methods, without having to scroll down through the code. Macro is just a method that writes code for us. This is where the macros come to play.

We have three types of macros here: attr_accessor, attr_reader, and attr_writer. The reader as the name implies is used to set data that doesn't need to change throughout the code i.e id, name, etc... The writer or the setter is used to set an attribute that you can change over time.

class Personattr_reader :name
attr_writer :age
def initialize(name)
@name = name
@age = age
enddef age
" I'm #{@age} years old"
end
endselam = Person.new("Selam")

What if you have data that is going to get data but also set the data? It can be an email address, home address, etc.. this is when we would use an accessor. The accessor is used when we have data that needs to be updated and read. Think about it, your email address can change or home address in fact so we set that attribute as an accessor. Here is how we would write that:

class Personattr_accessor :name, :age, :sex, :email_address   def initialize(name)
@name = name
end
end

^this is so much easier than having to write:

   def initialize(name)
@name = name
@age=age
@sex=sex
@email=email
end def name
@name
end
def name=(name)
@name
end
def age
@age
end
def age=(age)
@age
end

To conclude this, if you are not sure if your method is going to be a reader or writer yet, you can initialize it and set the attribute to accessor and later change it if you decide you want the method to be a reader only. Hope this was helpful, I have found the more practice you do, the easier it will be to set the attribute so don’t worry if you are new to Ruby and don’t understand everything yet.

--

--