【初学者向け】Rails(ActiveRecord)でselfの理解を深める - インスタンスメソッド クラスメソッド -

# はじめに
本記事は、著者自身のクラスに対する理解を深めるために
例を用いてクラスについて解説していく記事となります！

# 対象の読者像
・Railsでselfの使い方がイマイチ掴めていない方
・Rails触ったことあるけどselfの理解が曖昧な方

# 基本事項
```ruby:example.rb
class Example
  attr_accessor :person
  
  def initialize(person)
    @person = person
  end
  
  def self.ikemen
    self.person
  end

  def busamen
    self.person
  end

end
```
さて、問題です！

## 問1
クラスメソッドはどれのことを指すでしょうか?
<details><summary>答え</summary>


```rb
def self.ikemen
  self.person
end
```
</details>

## 問2
問1のクラスメソッドはどのように呼び出すでしょうか?
<details><summary>答え</summary>


```:ターミナル
Example.ikemen
```
</details>

## 問3
問2のクラスメソッドを呼び出すとどのような結果が返ってきますか?
また、なぜその結果になるのか説明して下さい。
<details><summary>答え</summary>


==>(戻り値)undefined method `person' for Example:Class (NoMethodError)
==>(理由)selfは、Exampleクラス自身であるため(personというクラス変数が存在しないためエラーになる)
</details>

## 問4
インスタンスメソッドはどれのことを指すでしょうか?
<details><summary>答え</summary>


```rb
def busamen
  self.person
end
```
</details>

## 問5
問4のインスタンスメソッドはどのように呼び出すでしょうか?
<details><summary>答え</summary>


```:ターミナル
busaiku = Example.new("motoya")
busaiku.busamen
```
</details>

## 問6
問5のインスタンスメソッドを呼び出すとどのような結果が返ってきますか?
また、なぜその結果になるのか説明して下さい。
<details><summary>答え</summary>


==>(戻り値)motoya
==>(理由)selfは、Example.new("motoya")で生成したインスタンス自身であるため
</details>

# Rails(ActiveRecord)でのself
前提として、下記の状態とします。
```ruby:schema.rb
ActiveRecord::Schema.define(version: 2022_08_23_103957) do

  create_table "tsubuyakis", force: :cascade do |t|
    t.string "title"
    t.string "content"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
  end

end
```
```ruby:tsubuyaki.rb
class Tsubuyaki < ApplicationRecord
  before_create :check_ikemen?

  def self.ikemen?
    where(title:"ikemen")
  end

  scope :ootuka, -> { where(title:"ikemen") }

  def check_ikemen?
    unless self.title == "ikemen"
      throw :abort
    end
  end

end
```

## 問7
上記のクラスメソッドはどれ？

<details><summary>答え</summary>


```ruby:答え
def self.ikemen?
  where(title:"ikemen")
end

scope :ootuka, -> { where(title:"ikemen") }
```
:::note
①実はscopeはクラスメソッドと同義
②where等、検索機能で使われる場合が多い
:::
>参考：[https://qiita.com/Ryuta1346/items/87be4100d7322a26acff](https://qiita.com/Ryuta1346/items/87be4100d7322a26acff)
</details>

## 問8
上記のインスタンスメソッドはどれ？

<details><summary>答え</summary>


```ruby:答え
def check_ikemen?
  unless self.title == "ikemen"
    throw :abort
  end
end
```
:::note
トランザクション処理で使われる
:::
</details>

## 問9
下記のようにターミナル上でcreateした場合どのようにインスタンスメソッドが振る舞われるか説明して下さい。

```:ターミナル
rails c
Tsubuyaki.create(title: "busamen", content: "busaiku")
Tsubuyaki.create(title: "ikemen", content: "motoya")
```

<details><summary>答え</summary>

Tsubuyaki.create(title: "busamen", content: "busaiku")
create前にcheck_ikemen?が作動して、
createしようとしたtitleが"ikemen"ではないので
トランザクション内の処理が失敗しロールバックされる。
(DB上に保存されない)

Tsubuyaki.create(title: "ikemen", content: "motoya")
createしようとしたtitleが"ikemen"なので正常にDB上に保存される

</details>

## 問10
下記のようにターミナル上でikemen?した場合どのようにクラスメソッドが振る舞われるか説明して下さい。

```:ターミナル
rails c
Tsubuyaki.ikemen?
```

<details><summary>答え</summary>

```:ターミナル
Tsubuyakiクラス (=tsubuyakisテーブル)に対して、
where(title:"ikemen")の条件に一致するデータを配列形式で取得する
今回は、データ1つしかないので下記が出力される

[#<Tsubuyaki:0x0000000122074158
  id: 1,
  title: "ikemen",
  content: "motoya",
  created_at: Thu, 08 Sep 2022 10:10:25.752938000 UTC +00:00,
  updated_at: Thu, 08 Sep 2022 10:10:25.752938000 UTC +00:00>]
```

</details>

# 終わりに
初学だとRailsとRubyは別個に考えがちですが
今回のようにRailsではselfはどうやって使ってるんだろう？
というテーマで考えると一段とRailsと仲良くなれた気がしました！
初学の方は是非お試しください！