🎓 A1Learner
🔍
0 of 34 lessons completed

Ruby Attribute Patterns

The beginner course used attr_reader, attr_writer and attr_accessor to write simple access methods. This lesson sets those lines beside hand-written versions and adds checks and computed readers.

attr lines beside hand-written twins

Dog uses attr_accessor for its name. Cat writes the same reader and writer by hand, and both animals end with a new name.

class Dog
  attr_accessor :name
  def initialize(name)
    @name = name
  end
end
class Cat
  def initialize(name)
    @name = name
  end
  def name
    @name
  end
  def name=(value)
    @name = value
  end
end
dog = Dog.new("Rex")
cat = Cat.new("Milo")
dog.name = "Max"
cat.name = "Ruby"
puts dog.name
puts cat.name

A writer that checks its value

The hand-written price writer stores zero when the new price is negative. A fair price passes through unchanged.

class Product
  attr_reader :price
  def initialize(price)
    @price = price
  end
  def price=(value)
    if value < 0
      @price = 0
    else
      @price = value
    end
  end
end
item = Product.new(10)
puts item.price
item.price = -5
puts item.price
item.price = 7
puts item.price

One line for two names

A single attr_accessor line names title and pages together. Both values can be read and set from outside.

class Book
  attr_accessor :title, :pages
  def initialize(title, pages)
    @title = title
    @pages = pages
  end
end
book = Book.new("Poems", 80)
puts book.title
puts book.pages
book.pages = 96
puts book.pages

A reader that computes

area stores nothing and multiplies the stored sides on each call. Changing the width changes the next area at once.

class Rectangle
  attr_writer :width
  def initialize(width, height)
    @width = width
    @height = height
  end
  def area
    @width * @height
  end
end
shape = Rectangle.new(4, 5)
puts shape.area
shape.width = 6
puts shape.area

Example

class Ticket
  attr_reader :price
  attr_accessor :seat
  def initialize(seat, price)
    @seat = seat
    @price = price
  end
  def price=(value)
    if value < 0
      @price = 0
    else
      @price = value
    end
  end
  def summary
    "#{@seat} costs #{@price}"
  end
end
ticket = Ticket.new("A1", 20)
puts ticket.summary
ticket.price = -3
puts ticket.price
ticket.seat = "B2"
puts ticket.summary

Key points

  • A hand-written reader returns the stored value, just like attr_reader.
  • A hand-written writer stores a new value, just like attr_writer.
  • A writer written by hand can check its value before storing it.
  • One attr_accessor line can name two values at once.
  • A reader can compute its answer from stored values on every call.

In this example, seat uses attr_accessor while price pairs a plain reader with a checking writer. Setting a negative price stores zero instead. summary computes its line from the current seat and price on every call.

Note

The attr lines and the hand-written methods give the same results when the jobs are plain.

Try it Yourself

Edit the code, then press Run.

Running is simulated

Exercise

In the checking writer from this lesson, what price is stored after item.price = -5?