Attributes (attr_accessor)

Ruby is a dynamic, beginner-friendly programming language, and attributes are how an object exposes its data — attr_accessor generates the getter and setter methods so you don't write them by hand.

Learn Attributes (attr_accessor) in our free Ruby course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick…

Part of the free Ruby course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

By the end of this lesson you'll understand getters and setters, use attr_reader/writer/accessor, and write custom accessors with validation.

What You'll Learn in This Lesson

1️⃣ The Manual Way: Getters and Setters

Instance variables are private to the object. To expose one, you write a getter (a method that returns it) and a setter (a method named with a trailing = that assigns it). Seeing this by hand makes the shortcut obvious.

2️⃣ attr_accessor, attr_reader, attr_writer

attr_accessor :name generates both the getter and the setter automatically. Use attr_reader for read-only data (a getter only) and attr_writer for write-only. You list the attributes as symbols.

Your turn. Add the right accessors to a Product class so its name is editable but its SKU is read-only. Complete the TODO s, then run it.

Write a custom temperature= setter that validates its input — the real payoff of writing accessors yourself. Run with ruby thermostat.rb .

📋 Quick Reference — Attributes

Practice quiz

What does attr_accessor :name generate?

  • Only a getter named name
  • Only a setter named name=
  • Both a getter (name) and a setter (name=)
  • An instance variable named name

Answer: Both a getter (name) and a setter (name=). attr_accessor writes both the getter and the setter for you at class-definition time.

Which macro creates a READ-ONLY attribute (getter only)?

  • attr_reader
  • attr_writer
  • attr_accessor
  • attr_const

Answer: attr_reader. attr_reader generates just the getter, so the value can be read but not written from outside.

If a class uses attr_reader :id, what happens when you call obj.id = 5?

  • It silently does nothing
  • It sets @id to 5
  • It creates a new attribute
  • It raises NoMethodError because no setter exists

Answer: It raises NoMethodError because no setter exists. attr_reader makes no setter, so assigning raises NoMethodError (undefined method 'id=').

How is a setter method named in Ruby?

  • set_name
  • name= (with a trailing equals sign)
  • name!
  • @name

Answer: name= (with a trailing equals sign). Ruby routes obj.name = x to the method name=(x); the trailing = is what makes it a setter.

You must pass attributes to attr_accessor as:

  • Symbols, like :name
  • Strings, like "name"
  • Instance variables, like @name
  • Local variables

Answer: Symbols, like :name. Accessor macros take symbols: attr_accessor :name, :age.

Inside an instance method, how do you correctly call the generated setter for name?

  • name = x
  • @name = x only
  • self.name = x
  • set name x

Answer: self.name = x. A bare name = x makes a local variable; self.name = x routes through the setter method.

attr_writer :password generates which method(s)?

  • A getter only
  • A setter only (write-only)
  • Both getter and setter
  • Neither

Answer: A setter only (write-only). attr_writer makes only the setter, useful for write-only values you don't want to expose.

Why would you hand-write a setter instead of using attr_accessor?

  • It runs faster
  • attr_accessor is deprecated
  • Hand-written setters are required by Ruby
  • To add validation or side effects when the value is set

Answer: To add validation or side effects when the value is set. A custom value= setter lets you validate or transform input — the payoff of writing it yourself.

Instance variables (the @-prefixed ones) are, by default:

  • Public and readable from anywhere
  • Private to the object — exposed only through methods
  • Shared across all instances
  • Automatically frozen

Answer: Private to the object — exposed only through methods. Instance variables are private; getters and setters are how you expose them to the outside.

Best practice for choosing accessors is usually to:

  • Always use attr_accessor
  • Never use accessor macros
  • Start with the least access (e.g. attr_reader) and widen only when needed
  • Use attr_writer for everything

Answer: Start with the least access (e.g. attr_reader) and widen only when needed. Default to read-only and add a setter only when callers truly need to change the value.