I entered from Rails and didn't know what [attr_accessor] was

A method called ** attr_accessor ** that appears frequently when looking at the basic grammar of Ruby.

When I first saw it, I didn't know what it was used for when I entered from Ruby on Rails.

I'll look it up from there

-** Method that handles both setter and getter ** -** Refer to and change the value of the instance variable **

To be honest, I can't understand ...

For those who know it, it may be too prescriptive to say what it is, but if anyone stumbles at the same place as me, I would appreciate it if you could refer to it.

Usage of attr_accessor

First of all, the ** attr_accessor ** method in question, but in a nutshell, it is a method ** that gives an instance an attribute that can be referenced and updated from the outside.

I will explain each one.

You cannot directly access the value of the instance

It's easy to forget when using Rails, but the main premise is that you can't directly access the values of ** instances. ** **

As an example, we have prepared the ** Hoge ** class below. There are two instance variables, ** name ** and ** age **.

attr_accessor.rb




class Hoge

  def initialize(name, age)
    @name = name
    @age = age
  end


  def hello
    p "Hello! I'm #{@name} "
    p "I'm #{@age} old"
  end
end

hoge = Hoge.new("hogehoge",12)
hoge.hello

p hoge.name

In this state, when I try to output the name which is a variable of hoge which is an instance of Hoge ...

"Hello! I'm hogehoge "
"I'm 12 old"
Traceback (most recent call last):
attr_accessor.rb:33:in `<main>': undefined method `name' for #<Hoge:0x0000000004e68eb8 @name="hogehoge", @age=12> (NoMethodError)

And NoMethodError occurs.

That should be it. This is because there is no method called name in the Hoge class.

Methods such as ** setter ** and ** getter ** come up to solve the problem of not being able to access the values of these instances.

Getter

Getters are used when you want to refer to the value of an instance as before. There are two ways to set getters: ** How to define methods ** and ** How to use access methods **.

The method of defining the method is really simple

python


class Hoge

  def initialize(name, age)
    @name = name
    @age = age
  end
 
 #Realize value reference by using the same name as the instance variable
  def name
    name = @name
  end

  def hello
    p "Hello! I'm #{@name} "
    p "I'm #{@age} old"
  end
end

Define a method that pulls an instance variable when executed.

However, this is a little uncool, so it is better to use the access method.

python


class Hoge
  attr_reader :name

  def initialize(name, age)
    @name = name
    @age = age
  end


  def hello
    p "Hello! I'm #{@name} "
    p "I'm #{@age} old"
  end
end

You can refer to the value of the instance variable as above by using the ** attr_reader ** method. The value defined at this time must be ** the same as the one defined in the instance variable **.

This is the role of a getter to refer to the value.

Setter

Now that you can refer to the value, try substituting another value for the instance value in the same way as Rails ...

python


class Hoge

  attr_reader :name

  def initialize(name, age)
    @name = name
    @age = age
  end

  def hello
    p "Hello! I'm #{@name} "
    p "I'm #{@age} old"
  end

end

hoge = Hoge.new("hogehoge",12)
hoge.hello
p hoge.name
hoge.name = "fugafuga"


--------------------------------------------------------------------------------

"Hello! I'm hogehoge "
"I'm 12 old"
"hogehoge"
Traceback (most recent call last):
attr_accessor.rb:37:in `<main>': undefined method `name=' for #<Hoge:0x0000000004fbb040 @name="hogehoge", @age=12> (NoMethodError)
Did you mean?  name

I will get angry again.

This is because ** getters can see values, but they can't assign new values because they don't include the ability to update **.

What is used to solve this problem is called a ** setter **.

There are two types of setters, one is to define the method as it is and the other is to use the accessor method.

python


def name=(name)
    @name = name
end

If you add ** = ** after the method, it becomes a setter. The content is simple, just reflect the received argument in the instance variable.

How to use accessor methods.

python


class Hoge

  attr_reader :name
  attr_writer :name

  def initialize(name, age)
    @name = name
    @age = age
  end

  def hello
    p "Hello! I'm #{@name} "
    p "I'm #{@age} old"
  end
end

The accessor method uses ** attr_writer **.

python


hoge = Hoge.new("hogehoge",12)
hoge.hello
p hoge.name
hoge.name = "fugafuga"
hoge.hello

------------------------------------------------------

"Hello! I'm hogehoge "
"I'm 12 old"
"hogehoge"
"Hello! I'm fugafuga "
"I'm 12 old"

And surely the value of name has been updated.

attr_accessor

It is finally the explanation of attr_accessor, but the role of this method is to be ** responsible for both getter and setter above.

In other words, you don't have to write two types, attr_reader and attr_writer

python


class Hoge
  #This party plays the role of getter and setter
  attr_accessor :name

  def initialize(name, age)
    @name = name
    @age = age
  end

  def hello
    p "Hello! I'm #{@name} "
    p "I'm #{@age} old"
  end
end

hoge = Hoge.new("hogehoge",12)
hoge.hello
p hoge.name
hoge.name = "fugafuga"
hoge.hello

----------------------------------------------------------

Hello! I'm hogehoge "
"I'm 12 old"
"hogehoge"
"Hello! I'm fugafuga "
"I'm 12 old"

Can be written fairly simply.

You may have wondered if you've read this far, but Rails usually doesn't show this accessor method.

Then, the reason why the table value can be referenced and updated like a method is because it is set automatically by ** ActiveRecord :: Base **.

If you like, I have written an article about that as well, so please have a look. >> rails db: migrate and the existence of models

This is the explanation of attr_accessor.

Summary

Method function role
attr_reader Getter You will be able to refer to the value of the instance variable
attr_writer Setter You will be able to update the value of an instance variable
attr_accessor Getter setter You will be able to refer to and update the values of instance variables

Ruby on Rails is a very useful framework, but I strongly felt that I had to re-learn the basics of Ruby from time to time ...

We encourage you to write your own code about the contents of this area!

Well then

Recommended Posts

I entered from Rails and didn't know what [attr_accessor] was
What I learned from studying Rails
I knew what reflection was
What I was addicted to while using rspec on rails
Rails does it automatically and it helps, but I was surprised
A note of what I stumbled upon and noticed in catching up with Laravel from Rails
What I was addicted to when implementing google authentication with rails
[Rails] What was the error message?
[Rails] What I learned from a little stumbling block when using ancestry
I was a little addicted to running old Ruby environment and old Rails
What I learned from Java monetary calculation
I didn't know what to write in Maven's scope so I looked it up