コメント機能の実装

# コメント機能の実装
## 概要
- ポートフォリオとして作成する学習マッチングアプリの中で、コミュニケーションツールを実装したい。
- twitterをイメージしたツールにしたい。
- ユーザ間のコミュニケーションを想定する。
## アソシエーション
![9cf19332afde24ac92928cee7c83ac90.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1923339/e10317da-4c74-cea8-4cd6-501d95ebb0a1.png)
## テーブル定義
### Commentsテーブル
[![Image from Gyazo](https://i.gyazo.com/546427b61330905b11df1bdc51113a00.png)](https://gyazo.com/546427b61330905b11df1bdc51113a00)
### ReplyRelationshipsテーブル
[![Image from Gyazo](https://i.gyazo.com/5344e7d8548f82091a8196deeb72edd2.png)](https://gyazo.com/5344e7d8548f82091a8196deeb72edd2)
## モデル
commentには、メインとなるコメントと返信コメントがある。そのため、同じCommentモデルで２つの異なるアソシエーションが必要となる。それを実現させるために、以下のようなアソシエーションを設定した。

### ReplyRelationshipモデル
[![Image from Gyazo](https://i.gyazo.com/810cd0e890074fd6204b22723de79d8e.png)](https://gyazo.com/810cd0e890074fd6204b22723de79d8e)
同じCommentモデルと２つの異なるアソシエーションを設定するために、class_nameを使用する。
このように宣言すると、@reply_relationship.main_commentや@reply_relationship.replyといった使い方ができる。
また、意訳すると、「Commentモデルに対して、main_commentって名前でbelongs_toの関連付けしときますね」ということになる。
今回は、返信コメントがある時に、このモデルが活躍するので、replyが削除された時点でreply_relationshipは不要であるため、replyのみ「dependent: :destroy」としている

### Commentモデル
[![Image from Gyazo](https://i.gyazo.com/75f12123ed325c4f92ec36259e5836a9.png)](https://gyazo.com/75f12123ed325c4f92ec36259e5836a9)
上記に付随する形で、CommentモデルでもReplyRelationshipモデルと２種類の異なるアソシエーションが必要となる。
[![Image from Gyazo](https://i.gyazo.com/6a93e63b1ddda090946b00b241b157fd.jpg)](https://gyazo.com/6a93e63b1ddda090946b00b241b157fd)
[![Image from Gyazo](https://i.gyazo.com/51c12637a3ca8ad8fdfefbf9ceeafd9c.jpg)](https://gyazo.com/51c12637a3ca8ad8fdfefbf9ceeafd9c)
まず、上記の２つは、class_nameを使用して、ReplyRelationshipモデルと異なる２つのアソシエーションを設定している。
このように宣言することで、＠comment.replying_relationshipや、@comment.replied_relationshipsのように使うことができる。
また、意訳すると、「ReplyRelationshipモデルに対して、reply_idを見て、replying_relationshipって名前でアソシエーション設定しますね」となる。
[![Image from Gyazo](https://i.gyazo.com/18d83f2847e4cf1b200b7aed5942a855.jpg)](https://gyazo.com/18d83f2847e4cf1b200b7aed5942a855)
[![Image from Gyazo](https://i.gyazo.com/5385a49ec49f46c81a7048e542c73180.jpg)](https://gyazo.com/5385a49ec49f46c81a7048e542c73180)
次に、上記の２つは、throughとsourceを使用している。それぞれ、

- through 経由するモデル名を指定する
- source　関連先モデル名を指定する

throughによる関連付けは、２つのモデルの間に第３のモデルが存在する場合に用いるのが一般的である。しかし、今回はComment → ReplyRelationship → Comment　であるため、sourceでそれぞれ名前付けをして区別している。また、上記で定義したReplyRelationshipモデルの名前をthroughに使用する。
このように宣言することで、@comment.replyingや@comment.repliedのように使うことができる。
また、意訳すると、「replying_relationshipモデルを経由して、main_commentモデルに対して、replyingって名前でアソシエーションしときますね」となる。
## まとめ
このようにすることで、CommentモデルとReplyRelationshipモデルで２種類の異なるアソシエーションを設定することができた。こうすることで、db上は同じCommentsテーブルに存在するにも関わらず、メインのコメントであるのか、返信コメントであるのかの区別ができるようになった。
Railsはあらかじじめかなり便利なメソッドが複数存在しているが、多言語で同じことをしようとした時に、どうやってアソシエーションを実現させるのか気になった。
コメントを返信する際に、返信コメント用のモーダルも実装したので、それも追記するか、新しい記事にしたいと思う。
## 参考
[【Railsチュートリアル】フォロー機能のアソシエーションを解説してみる](https://sado-tech.hateblo.jp/entry/2018/08/17/201629)
[【rails】Twitterのツイート機能のモデル構造を考えてみた](https://sado-tech.hateblo.jp/entry/2018/08/31/192523)
[公式　Active Record の関連付け](https://railsguides.jp/association_basics.html#has-many-through%E9%96%A2%E9%80%A3%E4%BB%98%E3%81%91)

### モーダル作成時に参考にした記事
[【Rails、JavaScript】モーダルウィンドウに写真詳細画面を表示させる](https://qiita.com/MitsuTurtle/items/3283832f5df2d3fcbeb7)