Ruby Attribute Writers and Readers

Posted by Francesca Dreith on January 25, 2020

Instance variables, denoted with a @ symbol, allow you to access information about the instance outside the scope of one particular method, within the scope of the instance. The purpose of an attribute writer method is to be able to assign local variables to an instance variable, and the purpose of an attribute reader method is to access the value of that instance variable.

In order for the reader method to read the variable, the variable needs to be defined. It is the job of the writer method to define the variable. A writer method looks like:


def name=(name_given)
	@name = name_given 
end


The writer method (name=), accepts an argument of a local variable (name_given), and sets it to be the value of the instance variable (@name). Writer methods are also referred to as “setter methods” because they set the value of an instance variable.

To allow access to the value of this instance variable, we need an attribute reader, or getter method to ask the instance of the class what the variables value is.

An attribute reader method looks like:

def name
	@name = name
end

The purpose of this reader method is reveal the value of the saved variable by to giving us the ability to call a method on an instance of the class to return the instance variable’s value. The reader method is also called the getter method because it “gets” or retrieves the value of the instance variable.

Now we can use the method .name to return a name of an instance of a variable, in this case let’s say on the Person class, person.name, will return the assigned name of that instance of a person in the form of a string.

An instance variable can be set to any data type. Above we defined it to a local variable because we were defining a method that can be used to pass in a data type through an argument to be set to that instance variable. In our example, if we wanted to set the value of name to a Person’s name, we would pass in a string, “Karen”, to set the value of @name = “Karen”. A string is an object that holds a group of characters — usually a word or sentence, between quotation marks. If you were to try to set your instance variable to, karen (without quotation marks, and lowercase because uncased would indicate an uninitialized constant), @name = karen, Ruby would think you were setting it to a variable of karen, which at this point is an empty variable.

A few things can go wrong without a writer and reader method:

1) If you do not have a writer method, and try to call an instance variable, @name, it will not give you an error message because it has a value of nil, and will return nothing.

2) If you do not have a reader method, and you try to call an undefined method on a class, Person.name, you will receive this error message:

NoMethodError:
       undefined method `name’ for Person:Class

3) If you call a variable without defining it, name, or if you call a defined variable outside of the scope of the method it was defined in (which is where instance variables come in handy), it will give an undefined local variable name error:

NameError:
       undefined local variable or method `name’ for Person:Class

Readers and writers are usually defined is by an attribute accessor class method: attr_accessor. This does the job of both attribute writers and attribute readers.

class Person
	attr_accessor   :name 

end

If you wanted the ability to read a variable (but not write), or write a variable (but not read it), you would use the attr_reader, or attr_writer methods, respectively.

class Person
	attr_accessor  :name 
	attr_reader    :age
	attr_writer    :opinions

end

In the above example, the Person’s name can be changes and accessed, we can read their age but not change their age, and their opinions can be changed, but not read by others.