attr_accessor and Instance Variables
Instance variables, prefixed with @, store the state that belongs to a specific object. They are private by default in the sense that there's no automatic external access to them -- unlike some languages where fields are public unless marked otherwise, Ruby requires you to define explicit methods to read or write an instance variable from outside the object. Because writing a plain getter (def name; @name; end) and setter (def name=(value); @name = value; end) by hand for every attribute is repetitive, Ruby provides the attr_reader, attr_writer, and attr_accessor class-level macros to generate these methods automatically.
Cricket analogy: Instance variables like @average are like a player's personal fitness data kept in the team physio's private file -- nobody outside can read or change it unless the physio explicitly hands out a report, just as Ruby requires an explicit getter or setter method to touch @average from outside.
attr_reader, attr_writer, and attr_accessor
attr_reader :name generates a method name that simply returns @name. attr_writer :name generates a method name= that assigns to @name. attr_accessor :name generates both, and is the most commonly used when an attribute needs to be both readable and writable from outside the object. All three accept multiple symbols at once, e.g. attr_accessor :name, :age, :email, generating pairs of methods for each.
Cricket analogy: attr_reader :average is like a scoreboard that only displays a player's average, attr_writer :average is like a scorer who can only update it after a match, and attr_accessor :average gives both display and update access in one declaration, just as attr_accessor :name, :age, :email sets up several stats at once.
class Product
attr_accessor :name, :price
attr_reader :sku
def initialize(name, price, sku)
@name = name
@price = price
@sku = sku
end
end
widget = Product.new("Widget", 9.99, "SKU-001")
widget.name # => "Widget" (via generated reader)
widget.price = 12.99 # via generated writer
widget.sku # => "SKU-001", read-only (no writer generated)
widget.sku = "SKU-002" # raises NoMethodError -- no attr_writer for skuWhy attribute methods matter beyond boilerplate
Because attr_accessor merely generates ordinary methods, you can later replace the generated writer with a custom one that adds validation, without changing any code that calls widget.price = 12.99 -- the caller doesn't know or care whether it's hitting a generated method or a hand-written one. This is Ruby's version of encapsulation: even though there's no strict private/public field syntax like Java, using accessor methods instead of ever exposing @price directly keeps a seam where validation or computed logic can be added later.
Cricket analogy: Because attr_accessor :average just generates plain methods, the scoring board can later swap in a custom average= that validates the number of innings played, without any commentator's script that calls player.average = 45.2 needing to change.
class Product
attr_reader :price
def price=(new_price)
raise ArgumentError, "price cannot be negative" if new_price.negative?
@price = new_price
end
endChoosing attr_reader over attr_accessor for an attribute is a deliberate design signal: it tells other developers 'this is read-only from outside the object,' enforcing immutability at the API level even though the underlying instance variable is technically still mutable from inside the object's own methods.
Instance variables that are never initialized (e.g. referenced before initialize sets them, or accessed on an object where a conditional branch skipped the assignment) simply evaluate to nil rather than raising a NameError, unlike undefined local variables. This can mask bugs -- always initialize every instance variable your class relies on inside initialize, even to a sensible default like 0 or an empty array.
- Instance variables (
@name) hold per-object state and have no automatic external accessors -- you must define them explicitly. attr_readergenerates a getter,attr_writergenerates a setter, andattr_accessorgenerates both for given symbols.- attr_accessor methods can be freely overridden with custom logic (e.g. validation) without breaking external callers.
- Choosing attr_reader instead of attr_accessor is a deliberate way to expose read-only attributes.
- Uninitialized instance variables evaluate to nil rather than raising an error, which can hide subtle bugs.
- Multiple attributes can be declared in one call, e.g.
attr_accessor :name, :age, :email.
Practice what you learned
1. What does `attr_accessor :price` generate?
2. What happens if you try to call `widget.sku = "X"` when only `attr_reader :sku` was declared?
3. Why might a developer prefer attr_reader over attr_accessor for a given attribute?
4. What value does an uninitialized instance variable evaluate to when accessed?
5. Can a hand-written method with the same name as an attr_accessor-generated method override it?
Was this page helpful?
You May Also Like
Classes and Objects in Ruby
Learn how Ruby defines classes as blueprints for objects, covering the `class` keyword, `initialize`, instance methods, and how everything in Ruby is an object.
Method Visibility
Learn how Ruby's public, private, and protected keywords control which parts of an object's interface callers can access, and why visibility shapes good API design.
Inheritance in Ruby
See how Ruby classes extend one another with single inheritance, how `super` calls parent implementations, and how method resolution order determines which method runs.
Operator Overloading
Learn how Ruby implements operators as ordinary methods, letting you define custom `+`, `==`, `<<`, and other operators on your own classes for expressive, idiomatic APIs.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics