attr_accessorとは

初めまして、2021年4月20日から実務未経験でプレイライフに入社したエンジニアの熊﨑です！
業務での学びや疑問点等を記事にすることで、少しでも読んでいただく皆様のお役に立てたらと思います。

## この記事の対象者
- railsはある程度経験がある（railsチュートリアルを完走した人）
- rubyでアクセサメソッドを定義したことのない人

## attr_accessorとは
rubyで使用されるアクセサメソッドを定義するメソッドです。

## そもそもアクセサメソッドとは？

> アクセサとは、オブジェクト指向プログラミングで、オブジェクト内部のメンバ変数（属性、プロパティ）に外部からアクセスするために用意されたメソッド。メンバ変数をオブジェクト内部に隠蔽し、外部から直接参照させないようにするために用意される。

[参考記事](https://e-words.jp/w/%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B5.html#:~:text=%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B5%E3%81%AE%E3%81%86%E3%81%A1%E3%80%81%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E5%86%85%E9%83%A8,%E3%83%AA%E3%83%BC%E3%83%80%E3%83%BC%EF%BC%88reader%EF%BC%89%E3%81%AA%E3%81%A9%E3%81%A8%E3%81%84%E3%81%86%E3%80%82)

これはどういうことかと言うと、「クラスから作られたインスタンス内の属性を変更したり、呼び出したりするために必要なメソッド」ということです。

## 具体例
ここまで文章だけ読んでもピンとこないと思うので、ここからは具体例を用いて説明したいと思います。

Userの名前を管理するモデルを作っていると仮定します。

```user.rb
class User
  def initialize(name)
    @name = name
  end
end
```

ここで試しにuser = User.new(name: '佐藤')と入力してみます。
すると以下のようなオブジェクトが返ってきます。

```
#<User:0x00007feb6aa43820 @name='佐藤'>
```

ここでインスタンス内のname属性の値を呼び出してみたいと思います。

```
user = User.new(name: '佐藤')
user.@name
SyntaxError: unexpected tIVAR
user.@name
　　　^~~~~
```
インスタンス変数はクラスの外部から参照できないので、エラーが出てしまいましたね。
railsを使った経験のある方ならなんとなくイメージできるかと思いますが、インスタンス内の属性を参照するにはuser.nameと書く必要があります。

```
user = User.new(name: '佐藤')
user.name
NoMethodError: undefined method `name' for #<User:0x00007fcee585d520 @name="佐藤">
```

nameメソッドがないとエラー文で言われているので、nameメソッドを定義する必要があります。

```user.rb
class User
  def initialize
    @name = name
  end

　def name
    @name 
  end
end
```

```
user = User.new(name: '佐藤')
user.name
=> '佐藤'
```
と出力されたと思います。

今度は佐藤さんではなくて、田中さんに名前を書き換えたいとします。

```
user = User.new(name: '佐藤')
user.name = '田中'
NoMethodError: undefined method `name=' for #<User:0x00007fcee585d520 @name="佐藤">
```
name=というメソッドがないよと言われてますね。
ですので今後は以下のようにuser.rbを書き直していきます。

```user.rb
class User
  def initialize
    @name = name
  end

　def name
    @name 
  end

  def name=(value)
     @name = value
  end
end
```

```
user = User.new(name: '佐藤')
user.name = '田中'
=> "田中"
user.name
=> '田中'
```

ちゃんと書き変わりましたね。このように、インスタンス内の値を書き換えたり、参照するには以下のようにメソッドを定義してあげる必要があります。しかし、属性が少ないならこれでも良いかもしれませんが、属性が多くなってくるとコードが長くなってしまいますね。

そこで、Rubyではアクセサメソッドというものがあり、先ほどのuser.rbをもっと簡単に書き換えることができます。

```
class User
  attr_accessor :name

  def initialize
    @name = name
  end
end
```

こう書くだけでUserモデルのインスタンス内のname属性を参照・変更することが出来ます。
こっちの方が記述量も少なくスマートですよね。
他にも参照だけしたい場合はattr_reader、変更だけしたい場合にはattr_writerというアクセサメソッドが存在するので、その時に応じて使い分けましょう。

## これってどんな時に使うの？
ここまで読んでいただいて、「使い方はわかったけどどんな時に使うの？ そもそもrailsでアプリ作った時にこんなの使わなかったよ」と思う方もいらっしゃると思います。ですので、どんな時に使うかも説明します。

DBにデータを保存する必要がないモデル（例えば検索機能の検索パラメータなど）を作成するときに使用します。
通常DBに保存する場合には、railsのApplicationRecordというクラスを継承しているため、アクセサメソッドを定義しなくてもuser.nameと書くだけで、インスタンス内の属性を読み込めてしまいます。しかし、DBにデータを保存しない場合は、自分でアクセサメソッドを定義する必要があります。（実務で実際にやりました。）

## まとめ
- attr_accessorはインスタンス内の属性を変更したり、参照する際に必要なメソッド
- 検索クエリなどのDBに保存する必要のないモデルを使用する際に使う。検索機能などはどんなwebサービスでも使用されることが多いため、この辺の理解はしっかりしておく必要がある。

## 最後に
アクセサメソッドに関しては、プログラミング学習を始めた初期に見たことがありましたが、正直全く覚えていませんでした。しかし、実務に入って結構使うことが多いと感じたのでこれから転職活動を始められる方はその辺の理解もしっかりしておくことが重要だと感じました。
現在基礎知識を補填するためにチェリー本を読んでいるのですが、その際にmoduleの勉強をしましたので、次回はmoduleについての記事を書こうと思います！