Bird
Raised Fist0
Rubyprogramming~15 mins

Attr_reader, attr_writer, attr_accessor in Ruby - Deep Dive

Choose your learning style10 modes available
Overview - Attr_reader, attr_writer, attr_accessor
What is it?
In Ruby, attr_reader, attr_writer, and attr_accessor are shortcuts to create methods that get and set object properties. Instead of writing separate methods to read or change an object's data, these keywords automatically create them for you. attr_reader creates a method to read a value, attr_writer creates a method to change a value, and attr_accessor does both. This helps keep code simple and clean.
Why it matters
Without these shortcuts, programmers would write many repetitive methods just to access or update object data, making code longer and harder to maintain. These keywords save time and reduce mistakes by automating common tasks. They make it easier to control how data inside objects is accessed or changed, which is important for building reliable programs.
Where it fits
Before learning these, you should understand Ruby classes, objects, and how methods work. After mastering attr_reader, attr_writer, and attr_accessor, you can explore more advanced topics like encapsulation, custom getter/setter methods, and metaprogramming in Ruby.
Mental Model
Core Idea
Attr_reader, attr_writer, and attr_accessor are Ruby's quick tools to create simple methods that read and write object data without extra code.
Think of it like...
It's like having a mailbox with a slot for receiving letters (reading) and a door to put letters inside (writing). Attr_reader gives you the slot, attr_writer gives you the door, and attr_accessor gives you both.
┌───────────────┐
│   Object      │
│ ┌───────────┐ │
│ │ Property  │ │
│ └───────────┘ │
│               │
│ attr_reader   │──▶ Read method (getter)
│ attr_writer   │──▶ Write method (setter)
│ attr_accessor │──▶ Both getter and setter
└───────────────┘
Build-Up - 7 Steps
1
FoundationUnderstanding Ruby Instance Variables
🤔
Concept: Instance variables store data inside an object and are private by default.
In Ruby, instance variables start with @ and hold data unique to each object. For example: class Person def initialize(name) @name = name # @name is an instance variable end end These variables cannot be accessed directly from outside the object.
Result
Instance variables keep data safe inside objects but can't be read or changed directly from outside.
Knowing that instance variables are private helps understand why we need methods to access or modify them.
2
FoundationWriting Manual Getter and Setter Methods
🤔
Concept: Methods can be written to read (getter) or change (setter) instance variables.
To access or update @name, you write methods: class Person def name # getter method @name end def name=(new_name) # setter method @name = new_name end end These methods let you read and write @name safely.
Result
You can now do: p = Person.new("Alice") puts p.name # outputs 'Alice' p.name = "Bob" # changes @name to 'Bob'
Understanding manual getters and setters shows why attr_reader and others are useful shortcuts.
3
IntermediateUsing attr_reader for Getter Methods
🤔Before reading on: do you think attr_reader creates a method to read, write, or both? Commit to your answer.
Concept: attr_reader automatically creates getter methods for instance variables.
Instead of writing a getter method, you can write: class Person attr_reader :name def initialize(name) @name = name end end This creates a method 'name' that returns @name.
Result
You can call p.name to get the value without manually defining the method.
Knowing attr_reader saves time and reduces repetitive code when you only need to read data.
4
IntermediateUsing attr_writer for Setter Methods
🤔Before reading on: does attr_writer create a method to read, write, or both? Commit to your answer.
Concept: attr_writer automatically creates setter methods to change instance variables.
Instead of writing a setter method, you can write: class Person attr_writer :name def initialize(name) @name = name end end This creates a method 'name=' that sets @name.
Result
You can do p.name = "Bob" to change the value without writing the method yourself.
Understanding attr_writer helps you control when and how object data can be changed.
5
IntermediateUsing attr_accessor for Both Getters and Setters
🤔Before reading on: does attr_accessor create getter, setter, or both methods? Commit to your answer.
Concept: attr_accessor creates both getter and setter methods automatically.
Instead of writing both methods, you can write: class Person attr_accessor :name def initialize(name) @name = name end end This creates both 'name' and 'name=' methods.
Result
You can read and write the @name variable easily with p.name and p.name = "Bob".
Knowing attr_accessor simplifies code when you want full access to an object's property.
6
AdvancedCustomizing Accessors Beyond attr_* Methods
🤔Before reading on: can you override attr_accessor methods with your own? Commit to your answer.
Concept: You can override or add logic to getter/setter methods even when using attr_accessor.
Sometimes you want to check or modify data when reading or writing: class Person attr_accessor :name def name=(new_name) @name = new_name.strip.capitalize end end This custom setter cleans the name before saving.
Result
Setting p.name = " alice " stores "Alice" with formatting applied.
Understanding you can customize accessors lets you combine convenience with control.
7
ExpertHow attr_* Methods Use Ruby's Metaprogramming
🤔Before reading on: do you think attr_accessor creates methods at runtime or compile time? Commit to your answer.
Concept: attr_reader, attr_writer, and attr_accessor use Ruby's metaprogramming to define methods dynamically at runtime.
When Ruby runs attr_accessor :name, it calls a method that creates new methods named 'name' and 'name=' on the class. This happens behind the scenes using Ruby's ability to write code that writes code. This dynamic method creation is powerful and flexible. You can even define your own methods that create methods dynamically using 'define_method'.
Result
The class gains new methods instantly without manual coding, making Ruby very flexible.
Knowing attr_* methods use metaprogramming reveals the power and magic behind Ruby's simplicity.
Under the Hood
Ruby's attr_reader, attr_writer, and attr_accessor are methods defined in the Module class. When called, they use Ruby's 'define_method' to create new instance methods dynamically. For attr_reader, it defines a method that returns the instance variable's value. For attr_writer, it defines a method that sets the instance variable. attr_accessor calls both. This happens at class definition time, so the methods exist when objects are created.
Why designed this way?
Ruby was designed to be expressive and concise. Writing many simple getter and setter methods was repetitive and cluttered code. Using metaprogramming to generate these methods automatically keeps code clean and readable. Alternatives like manually writing methods were error-prone and verbose. This design balances simplicity with flexibility.
Class Definition
   │
   ├─ attr_reader :name ──▶ defines method 'name' that returns @name
   ├─ attr_writer :name ──▶ defines method 'name=' that sets @name
   └─ attr_accessor :name ─▶ defines both 'name' and 'name='

At runtime:
Class ──> define_method('name') { @name }
Class ──> define_method('name=') { |val| @name = val }
Myth Busters - 4 Common Misconceptions
Quick: Does attr_accessor create a new instance variable automatically? Commit to yes or no.
Common Belief:attr_accessor creates the instance variable automatically when called.
Tap to reveal reality
Reality:attr_accessor only creates getter and setter methods; it does not create or initialize the instance variable itself.
Why it matters:Assuming the variable exists can cause errors if you try to read or write before initializing it, leading to unexpected nil values or bugs.
Quick: Can you add validation logic inside attr_writer methods? Commit yes or no.
Common Belief:attr_writer methods can include validation or extra logic automatically.
Tap to reveal reality
Reality:attr_writer creates simple setter methods without any logic; to add validation, you must write custom setter methods.
Why it matters:Relying on attr_writer for validation can cause data integrity issues if invalid data is assigned.
Quick: Does using attr_reader make the instance variable immutable? Commit yes or no.
Common Belief:attr_reader makes the variable read-only and immutable from outside the object.
Tap to reveal reality
Reality:attr_reader only prevents writing via a setter method, but the instance variable can still be changed inside the class or via other methods.
Why it matters:Thinking attr_reader guarantees immutability can lead to incorrect assumptions about object state and bugs.
Quick: Does attr_accessor always create public methods? Commit yes or no.
Common Belief:attr_accessor methods are always public and cannot be changed.
Tap to reveal reality
Reality:attr_accessor creates public methods by default, but you can change their visibility using Ruby's 'private' or 'protected' keywords.
Why it matters:Assuming these methods are always public limits your ability to control access and encapsulation.
Expert Zone
1
attr_accessor methods are defined on the class's singleton class, allowing dynamic method lookup and overriding.
2
Using attr_* methods does not prevent you from later redefining the getter or setter with custom logic, enabling flexible design.
3
attr_accessor can be combined with Ruby's 'freeze' method to create effectively read-only attributes after initialization.
When NOT to use
Avoid attr_accessor when you need strict control over how data is set or retrieved, such as validation, logging, or computed properties. Instead, write custom getter and setter methods. Also, for sensitive data, consider using private setters or no setters at all to protect object integrity.
Production Patterns
In real-world Ruby applications, attr_accessor is commonly used for simple data objects or value objects. For domain models, developers often use attr_reader with custom setters to enforce rules. Frameworks like Rails use attr_accessor for virtual attributes that don't map directly to database columns. Metaprogramming techniques extend attr_* usage for dynamic attribute handling.
Connections
Encapsulation in Object-Oriented Programming
attr_reader, attr_writer, and attr_accessor are tools to implement encapsulation by controlling access to object data.
Understanding these Ruby keywords deepens your grasp of how encapsulation protects and manages internal object state.
Metaprogramming
attr_* methods use metaprogramming to dynamically create methods at runtime.
Knowing this connection reveals how Ruby's flexibility comes from powerful metaprogramming features.
Access Control in Security
Like access control in security systems, attr_* methods regulate who can read or write data inside objects.
Seeing attr_* as access control helps appreciate the importance of controlling data flow and protecting integrity.
Common Pitfalls
#1Trying to read an instance variable without initializing it first.
Wrong approach:class Person attr_reader :name end p = Person.new puts p.name # No @name set yet
Correct approach:class Person attr_reader :name def initialize(name) @name = name end end p = Person.new("Alice") puts p.name
Root cause:Assuming attr_reader creates or initializes the variable, but it only creates the getter method.
#2Using attr_writer but expecting to read the value directly.
Wrong approach:class Person attr_writer :name def initialize(name) @name = name end end p = Person.new("Alice") puts p.name # Error: undefined method 'name'
Correct approach:class Person attr_writer :name attr_reader :name def initialize(name) @name = name end end p = Person.new("Alice") puts p.name
Root cause:attr_writer only creates setter methods, so no getter exists unless explicitly added.
#3Overwriting attr_accessor methods without calling super or handling carefully.
Wrong approach:class Person attr_accessor :name def name=(new_name) @name = new_name.upcase end end p = Person.new p.name = "alice" puts p.name # Outputs 'ALICE'
Correct approach:class Person attr_accessor :name def name=(new_name) @name = new_name.strip.capitalize end end p = Person.new p.name = " alice " puts p.name # Outputs 'Alice'
Root cause:Not handling input properly in custom setter can cause unexpected data formats.
Key Takeaways
attr_reader, attr_writer, and attr_accessor are Ruby shortcuts to create getter and setter methods automatically.
They help keep code clean by reducing repetitive method definitions for accessing object data.
attr_reader creates read-only access, attr_writer creates write-only access, and attr_accessor creates both.
These methods do not create or initialize instance variables; you must do that yourself.
Behind the scenes, these keywords use Ruby's metaprogramming to define methods dynamically at runtime.

Practice

(1/5)
1. What does attr_reader do in a Ruby class?
easy
A. Creates a method to read an attribute value
B. Creates a method to write an attribute value
C. Creates methods to both read and write an attribute
D. Deletes an attribute from the class

Solution

  1. Step 1: Understand attr_reader purpose

    attr_reader defines a getter method for an instance variable, allowing you to read its value.
  2. Step 2: Compare with other attr methods

    attr_writer creates a setter (write) method, and attr_accessor creates both getter and setter methods.
  3. Final Answer:

    Creates a method to read an attribute value -> Option A
  4. Quick Check:

    attr_reader = read method [OK]
Hint: attr_reader = read only method [OK]
Common Mistakes:
  • Confusing attr_reader with attr_writer
  • Thinking attr_reader allows writing values
  • Mixing attr_accessor with attr_reader
2. Which of the following is the correct syntax to create both getter and setter methods for @name in Ruby?
easy
A. attr_writer :name
B. attr_accessor :name
C. attr_reader :name
D. attr_both :name

Solution

  1. Step 1: Recall attr_accessor usage

    attr_accessor creates both getter and setter methods for the given symbol.
  2. Step 2: Check other options

    attr_reader only creates getter, attr_writer only setter, and attr_both is invalid syntax.
  3. Final Answer:

    attr_accessor :name -> Option B
  4. Quick Check:

    attr_accessor = read + write [OK]
Hint: Use attr_accessor for read and write [OK]
Common Mistakes:
  • Using attr_reader when write is needed
  • Using invalid method names like attr_both
  • Confusing attr_writer with attr_accessor
3. What will be the output of this Ruby code?
class Person
  attr_writer :age
  def initialize(age)
    @age = age
  end
  def show_age
    @age
  end
end

p = Person.new(30)
puts p.show_age
p.age = 40
puts p.show_age
medium
A. 30\n40
B. 30\n30
C. Error: undefined method `age='
D. Error: undefined method `show_age'

Solution

  1. Step 1: Understand attr_writer effect

    attr_writer :age creates a setter method age=, but no getter method is created.
  2. Step 2: Analyze method calls

    p.show_age returns @age which is 30 initially. Then p.age = 40 sets @age to 40. But p.show_age returns @age which is now 40.
  3. Step 3: Check output

    Actually, p.show_age is called twice, before and after setting age. So outputs are 30 then 40.
  4. Final Answer:

    30\n40 -> Option A
  5. Quick Check:

    attr_writer allows setting, show_age reads @age [OK]
Hint: attr_writer only sets; custom getter needed [OK]
Common Mistakes:
  • Assuming attr_writer creates getter method
  • Expecting error on p.age= assignment
  • Confusing show_age method with attr_reader
4. Identify the error in this Ruby class:
class Car
  attr_reader :model
  def initialize(model)
    @model = model
  end
  def model=(value)
    @model = value
  end
end

car = Car.new('Sedan')
car.model = 'SUV'
puts car.model
medium
A. Error: attr_reader conflicts with manual setter method
B. Error: undefined method 'model='
C. Error: attr_reader does not create setter method
D. No error, code runs and prints 'SUV'

Solution

  1. Step 1: Check attr_reader and setter method

    attr_reader :model creates a getter method. The setter method model= is manually defined.
  2. Step 2: Analyze method calls

    car.model = 'SUV' calls the manual setter, updating @model. puts car.model calls the getter from attr_reader, printing 'SUV'.
  3. Final Answer:

    No error, code runs and prints 'SUV' -> Option D
  4. Quick Check:

    attr_reader + manual setter works [OK]
Hint: attr_reader + manual setter is valid [OK]
Common Mistakes:
  • Assuming attr_reader creates setter method
  • Thinking attr_reader conflicts with manual setter
  • Expecting error on model= assignment
5. You want a Ruby class Book where the title can be read but not changed, and the author can be both read and changed. Which attribute methods should you use?
hard
A. attr_writer :title attr_writer :author
B. attr_writer :title attr_reader :author
C. attr_reader :title attr_accessor :author
D. attr_accessor :title attr_writer :author

Solution

  1. Step 1: Determine access for title

    Title should be readable but not writable, so use attr_reader :title.
  2. Step 2: Determine access for author

    Author should be readable and writable, so use attr_accessor :author.
  3. Final Answer:

    attr_reader :title attr_accessor :author -> Option C
  4. Quick Check:

    Read-only + read-write = attr_reader + attr_accessor [OK]
Hint: Use attr_reader for read-only, attr_accessor for read-write [OK]
Common Mistakes:
  • Using attr_writer for read-only attribute
  • Using attr_accessor for read-only attribute
  • Mixing up read and write access
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard