Skip to content
AgileLogics
5 min read

Accessors: attr_reader, attr_writer, attr_accessor

Prerequisites: Classes and objects

Instance variables are private to their object: code outside the object can't read rex.@name. To expose them, you write methods — and Ruby has shortcuts that write those methods for you.

Writing them by hand

class Product
  def initialize(name)
    @name = name
  end

  def name        # a "getter"
    @name
  end

  def name=(value) # a "setter" — note the = in the name
    @name = value
  end
end

The shortcuts

Shortcut Creates
attr_reader a getter only (read)
attr_writer a setter only (write)
attr_accessor both a getter and a setter

Example

class Product
  attr_reader :name
  attr_accessor :price

  def initialize(name, price)
    @name = name
    @price = price
  end
end

book = Product.new("Ruby Book", 30)
puts book.name
book.price = 25
puts book.price
book.name = "Other"

Expected output

Ruby Book
25
product.rb:15:in '<main>': undefined method 'name=' for an instance of Product (NoMethodError)

book.name = "Other"
    ^^^^^^^

name only has a reader, so trying to assign it fails. That's the point: attr_reader lets you decide which data outsiders may change.

Prefer attr_reader by default. Objects whose data can't be changed from outside are easier to reason about. Add a writer only when changing that value from outside genuinely makes sense — and consider a method that validates it instead:

class Product
  attr_reader :price

  def initialize(price)
    self.price = price
  end

  def price=(value)
    raise ArgumentError, "price can't be negative" if value.negative?

    @price = value
  end
end

p Product.new(10).price
10

Inside the class, self.price = value calls the setter method. Writing just price = value would create a local variable instead — self. is required for setters.

Common mistakes

  • Writing price = 5 inside a method and expecting the setter to run. Use self.price = 5.
  • Using attr_accessor for everything, which lets any code change any value and makes bugs harder to track down.