🔰【rails】テーブルから「レコード取得」➡「レコードの値加工」に役立つメソッド

>どうもaono1234と申します。記事がいいなと思ったらtwitterのフォローもお待ちしております‼
https://twitter.com/takeshi_program

今日はrailsでよく使うメソッド達を順序立てて皆さんにいくつか紹介したいと思います。😆
(すぐに結論を見たい人は`2.先に結論`の関係図をみて頂ければ幸いです。)


プログラムは大まかには以下3つのフェーズに大別することができます。

1. データベースから特定レコードを取得する。
2. 取得したものを使いやすいように加工する。
3. view（ブラウザ）で表示させる。


今回の記事では`1.` 、`2.`の部分でよく使われる便利メソッドを紹介したいと思いますので、
よろしくお願い致します。😄

# 1. はじめに
本記事は以下の読者が対象です。

- プログラミング初学者
- rails を使い始めたばかりの人
- eachメソッドを使ったことがある人

# 2. 先に結論
- 取得用の便利メソッド
    - find
    - find_by
    - where
 - 加工用の便利メソッド
     - ids
     - pluck

<b>各メソッドの関係図</b>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2534058/8977a3aa-e2ba-0c63-6289-0981c8fd49c2.png)


# 3. 取得用の便利メソッド
前提条件として`Task`というモデルをrails上で作ります。(モデルがなにか分からない人はrailsのMVC構造を学んでください)
この`Task`モデルは`taks`テーブルを操作するクラスです。

`tasks`テーブルには以下の`id`カラムと`name`カラムが定義されているとします。
|id | name |
| ---- | ---- |
|1|掃除|
|2|	朝礼|
|3|	終礼|
|4|	電話対応|

## 3.1 findとfind_byについて
この`tasks`テーブルから、`name`カラムが`掃除`のレコードを取り出したい時は
`findメソッド`を使うと簡単に取得することができます。
```ruby
Task.find(1) # id:1 のレコードが取得できる
```
今は`id: 1`のnameカラムに`掃除`があると分かっているから`id: 1`のレコードを取得すればよいと判断できましたが
どのレコードに掃除が入っているか、わからない場合はどうすればよいでしょうか？

その場合に便利なのが `find_by`メソッドです。
`find_by`メソッドを使えば、条件に合ったレコードを検索し、取得することができます。
```ruby
Task.find_by(name: '掃除') # id:1 のレコードが取得できる
```
ちなみに`find_by(id: 1)`とすれば`find(1)`と同じことができます


:::note warn
`find`メソッドは検索したが、レコードがひとつも該当しない場合<b>エラーを出力する</b>
```ruby
Task.find(100) #tasksテーブルにはid:100というレコードはないためエラーが出力される
```
`find_by`メソッドは、レコードがひとつも該当しない場合ても<b>エラーを出力しない</b>
```ruby
Task.find_by(id: 100) #nilが出力される
```
:::

## 3.2find_byとwhereについて
前述のとおり`find_by`は検索ができました。
しかし、`find_by`メソッドの仕様として、<b>「検索に最初に引っかかった1つのレコード」</b>しか取得することができません。
そのため、以下のように
:nameカラムに`掃除`が入っているレコードを全て取得したい場合、`find_by`ではできません。
|id | name |
| ---- | ---- |
|1|掃除|
|2|	朝礼|
|3|	終礼|
|4|	電話対応|
|5|	掃除|

```ruby
Task.find_by(name: '掃除')　#id: 1　のレコードしか取得できない
```

この場合に役立つのが`where`メソッドです。
```ruby
Task.where(name: '掃除')　#id: 1とid:5の複数レコードが入った配列を取得できる
```
:::note
`where`の引数には配列を利用することもできます。
```ruby
Task.where(name: ['掃除','朝礼']) #id: 1、id: 2、id:5の複数レコードが入った配列を取得できる
```
:::

# 4. 加工用の便利メソッド
`where`で取得したレコードたち
```ruby
Task.where(name: ['掃除','朝礼']) # [レコード1,レコード2,レコード3]
```
を実際にブラウザで表示させる場合に
このままの状態では使い勝手が悪い場合がりあります。

## 4.1 eachメソッド
例えばレコードの`id`だけ抽出して`[1,2,5]`のような配列に変換したい場合です。
そんなときにもっとも簡便な方法として`each`メソッドを使用するやり方があります。

```ruby
tasks = [] #空の配列を用意
Task.where(name: ['掃除','朝礼']).each do |task|
    tasks.push(task.id)
end 

p tasks #[1,2,5]がtasksが出力される
```
このように`each`メソッドを使えば`id`だけを抽出した配列に変換することが可能です。

## 4.2 idsメソッド
`each`メソッドは非常に汎用的なメソッドで便利なのですが、
railsでは`each`メソッドを内包した、より便利なメソッドがあります。
その1つが`ids`メソッドです。
このメソッドは`each`メソッドの処理を`ids`メソッド内で行ってくれます。
```ruby
p Task.where(name: ['掃除','朝礼']).ids #[1,2,5]がtasksが出力される
```
このように`ids`メソッドを使えばコードが1行で済み、可読性を向上させることができます。

## 4.3 pluckメソッド
`ids`メソッドを使えば、レコードの配列をワンタッチで`id`だけの配列にできました。
しかし、`id`だけではなく他のカラムでもしたくないですか？

そのような要望を満たしてくれるメソッドが`pluck`メソッドです。
`pluck`メソッドを使えば、`id`以外のカラムについても同じような出力を得ることができます。


```ruby
Task.where(name: ['掃除','朝礼']).pluck(:name) #[掃除,朝礼,掃除]が出力される
```
:::note
ちなみに`pluck`メソッドの引数に`id`カラムを指定してあげれば、`ids`と同じことができます。
```ruby
Task.where(name: ['掃除','朝礼']).pluck(:id) #[1,2,5]が出力される（idsと同じ出力）
```
:::

# 5.取得用メソッドと加工用メソッドの関係図
紹介したメソッド達を関係図としてまとめました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2534058/8977a3aa-e2ba-0c63-6289-0981c8fd49c2.png)

# 6. さいごに
どうでしたでしょうか？紹介したメソッドは参考になりましたでしょうか？

私はそれぞれのメソッドを単体で知った時はどのようなメリットがあるのかイメージが湧きませんでした。
しかし、各メソッドの繋がり・全体像を知ることで適材適所に合ったメソッドが使えるようになったと思います。

今後も便利なメソッドを紹介できればと思っておりますので、
次回の記事もご覧になって頂けると幸いです！😀