Ruby's attr_accessor is not an accessor

One of the classic mistakes in Ruby beginner articles is that attr_accessor is called an" accessor ". It seems that there are cases where the wording is simply wrong, and there are cases where it is not understood correctly in the first place.

In the case of Ruby, the accessor is

It is a general term for. Let's look at a typical example below

class Person
  def name
    @name
  end

  def name=(name)
    @name = name
  end
end

a_person = Person.new
a_person.name = "Kaoru"
puts a_person.name # => "Kaoru"

I have defined two methods, where name is the getter andname =is the setter. These two are collectively called an accessor. As a convention

(It's a convention, not a rule).

Methods whose names end in = are called "assignment methods" and are treated a bit specially in Ruby syntax. In the above example

a_person.name = "Kaoru"

As I wrote, you can put a space before = when calling a method. The code above is a type of assignment expression [^ ae].

[^ ae]: Ruby's assignment expressions are not limited to assignments to variables.

Not only that. You can also write a self-assignment expression using the assignment method. Let's look at the code below (assuming the class definition is as above).

a_person = Person.new

# (1)
a_person.name ||= "Kaoru"
puts a_person.name # => "Kaoru"

# (2)
a_person.name ||= "Haruka"
puts a_person.name # => "Kaoru"

(1)Now, instance variables@nameHas not yet been set to (when read)nilSelf-assignment operator in the state||=Because I am using@nameThe value of"Kaoru"Will be.

However, in (2), the assignment does not occur because the string object is assigned to @ name. Therefore, the return value of a_person.name is"Kaoru"instead of"Haruka".

Pretending to be longer. Let's get into the main subject from here. Looking at the class definition above, the getter and setter definitions spend three lines each (albeit simple). If you have 5 instance variables and you want to define a getter and a setter for each, you'll need 30 lines. This is ridiculous.

So, if you want to define such a simple getter or setter, [^ simp]

class Person
  attr_accessor :name
end

You just have to write.

[^ simp]: There is a reason I wrote "simple". Sometimes you want to define a non-simple accessor. Especially in the case of setters, you may want to apply some normalization (such as unifying full-width / half-width characters or deleting extra spaces) to a given argument before assigning it to an instance variable. In such cases, attr_accessor cannot be used.

I often see articles that describe this attr_accessor as an" accessor ". However, attr_accessor defines an accessor, not an accessor in itself. Perhaps even though part of the name has "accessor", it is dragged and thinks it is "accessor".

By the way, who is attr_accessor? If you come from another language, you might think it's part of Ruby's class definition syntax, but there's no such grammar. attr_accessor is just a method. Reference: Module # attr_accessor (Ruby 3.0.0 Reference Manual)

In other words

attr_accessor :name

Is just calling the method attr_accessor with the symbol: name as an argument. This will define the accessor in the class. attr_accessor is a method ** that defines a ** method.

To supplement a little

about it. Here's the code to check the last point:

class Hoge
  p name # => "Hoge"
end

In this code, name is not a local variable. Since there is no assignment expression to name before this point, it cannot be a local variable. Then it should be a method call. The receiver is not written in this method call. Since this is in a class definition expression, the receiver for name is the Hoge class. Since Hoge is an instance of a class called Class, name is a method that returns the class name / module name. So you will see "Hoge ". Reference: Module # inspect (Ruby 3.0.0 Reference Manual)

If you can understand the above,

class Person
  attr_accessor :name
end

Is

class Person
end

Person.attr_accessor(:name)

You will find that it is the same as writing.

Recommended Posts

Ruby's attr_accessor is not an accessor
What is Ruby's attr_accessor?
What is an interface?
What is Ruby's self?
What is an initializer?
What is an operator?
Yarn is not installed
What is an annotation?
When an error occurs even though validation is not set
[Memorandum] What is an error?
"tx" is not bound error
Ruby # {} is not variable expansion
What exactly is an API?
[Ruby] What is an instance?
Is it an Android app?
[Rails] fields_for is not displayed
Arrays.binarySearch is an exact match