タグ付け機能

# タグ付け機能の実装
## 概要
- ポートフォリオ作成として、学習マッチングサイトを作成。サイト内で講座を作る際にタグ付けを実装したい。
- ユーザーが自由にタグ付けできるようにしたい。
## 環境
- Rails 5.2.6
- ruby 2.6.3
## アソシエーション
![6ab4f133dfb54bd244def97a350b6d3e.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1923339/09bc2f44-8b8e-c54d-a0e1-acdbf83bc5d8.png)
講座(Lessonsテーブル)は複数のタグを持ち、タグ（Tagsテーブル）は複数の講座を持つため、講座：タグ＝多：多となるため、中間テーブルとして、TagListsテーブルを作成した。
## テーブル定義
[![Image from Gyazo](https://i.gyazo.com/f0670c7ffdc63ac92e8c8b122e24a1a0.png)](https://gyazo.com/f0670c7ffdc63ac92e8c8b122e24a1a0)
[![Image from Gyazo](https://i.gyazo.com/b42b1c3d874ddb5d8e3d25fbf8776380.png)](https://gyazo.com/b42b1c3d874ddb5d8e3d25fbf8776380)
## モデル
[![Image from Gyazo](https://i.gyazo.com/f5c5866226b90875d5155f1b0c5708ed.png)](https://gyazo.com/f5c5866226b90875d5155f1b0c5708ed)
[![Image from Gyazo](https://i.gyazo.com/c27e8c309b5fbe7ada39f1e6cff03f5c.png)](https://gyazo.com/c27e8c309b5fbe7ada39f1e6cff03f5c)
[![Image from Gyazo](https://i.gyazo.com/0b18a9894912d89b8f51095c4c1f070a.png)](https://gyazo.com/0b18a9894912d89b8f51095c4c1f070a)
## コントローラ
Lessonsコントローラ
- createメソッド
[![Image from Gyazo](https://i.gyazo.com/4b74df25dc32add6563aca78aec681bc.png)](https://gyazo.com/4b74df25dc32add6563aca78aec681bc)
- updateメソッド
[![Image from Gyazo](https://i.gyazo.com/2e8afa5db25bf5aa8232e35289904cae.png)](https://gyazo.com/2e8afa5db25bf5aa8232e35289904cae)
createメソッドもupdateメソッドも、フォームにタグの名前を入力して、@lesson（インスタンス変数）に格納し、送信後に各メソッド内でparamsとして展開して、名前を配列としてtag_listに格納し、@lessonに対して、tag_listを引数にsave_tagメソッドを呼び出している。
## save_tagメソッド
save_tagメソッドは、Lessonモデルに定義されている。
[![Image from Gyazo](https://i.gyazo.com/146a03a43027585fbf3009bfcf601ae5.png)](https://gyazo.com/146a03a43027585fbf3009bfcf601ae5)
- 既に@lessonに関連付けされているタグを取得し、nameカラムを配列に格納する。pluckは引数にカラムの値を指定して、その配列を返すメソッドである。
[![Image from Gyazo](https://i.gyazo.com/7df0c5c1af671e85cbb7aa132edae416.jpg)](https://gyazo.com/7df0c5c1af671e85cbb7aa132edae416)
- 既に@lessonに関連づけられていたが、新たに作成したタグには存在しないタグをold_tagsに格納する。
- 新たに作成したタグの内、既に@lessonに関連づけられていたタグ以外のタグをnew_tagsに格納する。
[![Image from Gyazo](https://i.gyazo.com/35f03f164d7e572e5cb156253c58acdb.jpg)](https://gyazo.com/35f03f164d7e572e5cb156253c58acdb)
- ①old_tagsを元に、該当するtagと、tagと@lessonとを関連づけるtag_listを定義する。
[![Image from Gyazo](https://i.gyazo.com/420095e184afea3e9cb64fe3db7d761a.jpg)](https://gyazo.com/420095e184afea3e9cb64fe3db7d761a)
- ②該当するtagが関連づけられたlessonが複数存在する場合には、tagのデータを削除すると、他の関連づけられたlessonで障害が生じるため、上記で定義したold_tag_listのみ削除する。関連づけられたlessonが１つしか存在しない場合は、どちらも削除する。
[![Image from Gyazo](https://i.gyazo.com/f2e8aff296cdf507355ba10c76ac5e8d.jpg)](https://gyazo.com/f2e8aff296cdf507355ba10c76ac5e8d)
- ③find_or_create_byは条件を指定して初めの1件を取得し1件もなければ作成するメソッドである。Tagモデルに対して、find_or_create_byメソッドを呼び出して、new_tagに格納する。その後、self.tags（@lessonに関連づけされたtagの配列）にnew_tagを追加する。<<は配列に対して行うインスタンスメソッドであり、「Array << 要素」のように要素を追加するメソッドである。
[![Image from Gyazo](https://i.gyazo.com/c6d020a1cf492db353148a67512812c3.jpg)](https://gyazo.com/c6d020a1cf492db353148a67512812c3)
#### lessonを新規作成の場合は、①、②は空配列に実行されるため、何も変更が生じないが、③は実行される。一方、lessonのタグを編集する際には、①、②、③が実行され、削除及び追加が行われる。
## まとめ
このようにして、タグ付け機能を実装しました。whereは配列を返し、find_byはレコードを返す点など、細かなrubyのメソッドの理解が必要な実装でした。とても勉強になりました。
以下は参考にした記事です。
https://qiita.com/kurawo___D/items/e9a2dd0bf46cca706e5c#2posts%E3%82%B3%E3%83%B3%E3%83%88%E3%83%AD%E3%83%BC%E3%83%A9%E3%81%ABsearch%E3%82%A2%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B
https://pikawaka.com/rails/pluck
https://pikawaka.com/rails/find_by
https://pikawaka.com/rails/where
https://docs.ruby-lang.org/ja/latest/method/Array/i/=3c=3c.html
https://railsdoc.com/page/find_or_create_by