What is attr_accessor in Ruby? What is attr_accessor in Ruby? ruby ruby

What is attr_accessor in Ruby?


Let's say you have a class Person.

class Personendperson = Person.newperson.name # => no method error

Obviously we never defined method name. Let's do that.

class Person  def name    @name # simply returning an instance variable @name  endendperson = Person.newperson.name # => nilperson.name = "Dennis" # => no method error

Aha, we can read the name, but that doesn't mean we can assign the name. Those are two different methods. The former is called reader and latter is called writer. We didn't create the writer yet so let's do that.

class Person  def name    @name  end  def name=(str)    @name = str  endendperson = Person.newperson.name = 'Dennis'person.name # => "Dennis"

Awesome. Now we can write and read instance variable @name using reader and writer methods. Except, this is done so frequently, why waste time writing these methods every time? We can do it easier.

class Person  attr_reader :name  attr_writer :nameend

Even this can get repetitive. When you want both reader and writer just use accessor!

class Person  attr_accessor :nameendperson = Person.newperson.name = "Dennis"person.name # => "Dennis"

Works the same way! And guess what: the instance variable @name in our person object will be set just like when we did it manually, so you can use it in other methods.

class Person  attr_accessor :name  def greeting    "Hello #{@name}"  endendperson = Person.newperson.name = "Dennis"person.greeting # => "Hello Dennis"

That's it. In order to understand how attr_reader, attr_writer, and attr_accessor methods actually generate methods for you, read other answers, books, ruby docs.


attr_accessor is just a method. (The link should provide more insight with how it works - look at the pairs of methods generated, and a tutorial should show you how to use it.)

The trick is that class is not a definition in Ruby (it is "just a definition" in languages like C++ and Java), but it is an expression that evaluates. It is during this evaluation when the attr_accessor method is invoked which in turn modifies the current class - remember the implicit receiver: self.attr_accessor, where self is the "open" class object at this point.

The need for attr_accessor and friends, is, well:

  1. Ruby, like Smalltalk, does not allow instance variables to be accessed outside of methods1 for that object. That is, instance variables cannot be accessed in the x.y form as is common in say, Java or even Python. In Ruby y is always taken as a message to send (or "method to call"). Thus the attr_* methods create wrappers which proxy the instance @variable access through dynamically created methods.

  2. Boilerplate sucks

Hope this clarifies some of the little details. Happy coding.


1 This isn't strictly true and there are some "techniques" around this, but there is no syntax support for "public instance variable" access.


attr_accessor is (as @pst stated) just a method. What it does is create more methods for you.

So this code here:

class Foo  attr_accessor :barend

is equivalent to this code:

class Foo  def bar    @bar  end  def bar=( new_value )    @bar = new_value  endend

You can write this sort of method yourself in Ruby:

class Module  def var( method_name )    inst_variable_name = "@#{method_name}".to_sym    define_method method_name do      instance_variable_get inst_variable_name    end    define_method "#{method_name}=" do |new_value|      instance_variable_set inst_variable_name, new_value    end  endendclass Foo  var :barendf = Foo.newp f.bar     #=> nilf.bar = 42p f.bar     #=> 42