[Rails]コメント削除機能の実装でハマってしまったので一応解決策を。

#はじめに
Railsの理解を深めるために、Twitterの機能を自装していく中で、あるTweetに対する**コメントの削除機能**をつけたところエラーが出続けるという沼にハマってしまいました。
エラー内容は`ActiveRecord::RecordNotFound (Couldn't find Comment without an ID)`です。
<img width="404" alt="スクリーンショット 2019-08-30 17.47.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475098/1e042131-2c94-93ab-896e-54132d4a6b41.png">

ParamsでID取得できてませんよーということでした。
一応解決はしたのでメモ程度に書いておきます。

※　結論としては、**ルート設定ミス**でした。
#リレーション

<img width="735" alt="スクリーンショット 2019-08-30 18.11.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475098/b85ae32d-5a78-417a-a860-79d29fad06cd.png">

CommentはUserとTweetの中間テーブルとして作成していきます。
今回のコメントの削除は、どのTweetのCommentか？というところが必要になります。

#エラー時実装内容
まずはエラーが起きてしまった時点での実装を書きます。
##ルート設定

```ruby:routes.rb

# ---中略--- #

  resources :tweets do
    resources :comments, only: [:create, :destroy]
  end
```
ネストにしているのはどのツイートに対するコメントかを簡単に設定するためです。
/tweets/**:tweet_id**/comments/:id(.:format)
![スクリーンショット 2019-09-02 10.23.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475098/dc8a8a1e-f721-222d-27bc-ca83dbd3cb8b.png)

結論としてはこれが引っかかってたみたいです。。
##コントローラー設定
削除機能に関するコントローラー設定は以下のように実装しました。
Commentテーブルから受け取ったCommentのidに該当するコメントを削除するというものです。

```ruby:comments_controller.rb
class CommentsController < ApplicationController

# ---中略--- #

  def destroy
    Comment.find(params[:id]).destroy
    redirect_to tweets_path
  end
end
```
今回は、削除後の先をTweets_pathとしTweet一覧画面に飛ばしてます。
##ビュー設定

前提として、@commentsに投稿されたコメントを引き渡した状態であるとして、、

```ruby:/tweets/show.html.erb

# ---中略--- #

<% @comments.each do |comment| %>
  <p><span>コメント内容: </span><%= comment.body %></p>
  <p><%=link_to "削除", tweet_comments_path(comment.id), method: :delete %></p>
<% end %>
```
![スクリーンショット 2019-09-02 10.23.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475098/dc8a8a1e-f721-222d-27bc-ca83dbd3cb8b.png)

ルーティングを確認すると、Tweet_comments DELEATは
`/tweets/:tweet_id/comments/:id(.:format)`であるので
パスの書き方は`tweet_comments_path`。
()の中身は取得したい`comment.id`を入れました。

##エラー結果
<img width="391" alt="スクリーンショット 2019-08-30 17.45.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475098/2778d673-9961-07a9-a563-e81572c36da4.png">
これらの実装のもと、「削除」をポチッと押したところ先程の`ActiveRecord::RecordNotFound (Couldn't find Comment without an ID)`というエラーになってしまうというものでした。

#実験
エラー文からきっと`tweet_comments_path(comment.id)`この書き方が正しくないのだろうと思ったので、試しに`tweet_comments_path(comment.tweet.id)`としてみることに。

```ruby:/tweets/show.html.erb

# ---中略--- #

<% @comments.each do |comment| %>
  <p><span>コメント内容: </span><%= comment.body %></p>
  <p><%=link_to "削除", tweet_comments_path(comment.tweet.id), method: :delete %></p>
<% end %>
```
コントローラーではTweet.idを引き受けます。

```ruby:comments_controller.rb
class CommentsController < ApplicationController

# ---中略--- #

  def destroy
    comment = Comment.find_by(tweet_id: params[:tweet_id])
    comment.destroy
    redirect_to tweets_path
  end
end
```

Comment.idの引き渡しはしないので、ネストしている部分は`resources`ではなく`resource`にします。
※`resources`のままだとルーティングエラーになります。

```ruby:routes.rb

# ---中略--- #

  resources :tweets do
    resource :comments, only: [:create, :destroy]
  end
```

実際の動かしてみると次のようになりました。
こちらの下の「コメント2つめ」の方を削除します。
<img width="279" alt="スクリーンショット 2019-08-30 18.58.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475098/2f7fcdc6-f7c9-27ea-52fe-fac77dda2822.png">
すると結果は、
<img width="261" alt="スクリーンショット 2019-08-30 19.03.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475098/10fbe320-610e-78e1-1747-dd026e811ef1.png">
上の「コメントします」の古い方のコメントが削除されてしまいました。

実験的にTweet.idしか引き渡していないのでそうなりますよね。
どのコメントを削除するか指定していないので。。

けど、ParamでのTweet.idの引き渡しはできたようです。
ルーティングをネストした場合は`comment.tweet.id`は引き渡せるけど、`comment.id`は引き渡せないのか、、よくわからん

※そもそも引き渡し部分を`comment.tweet.id`にしなくてはいけなかったのでは？
と思い、ルーティングとコントローラーの設定を戻してみましたが、その場合は`comment.id`を渡したいのに、`Tweet.id`引き渡してしまっているので当然エラーとなりました。

#解決策

ルーティング設定でcommentのdestroy部分をネストさせるのを諦めました。

```ruby:routes.rb

# ---中略--- #

  resources :tweets do
    resource :comments, only: [:create]
  end
  resources :comments, only: [:destroy]
```
comments#destroyのルーティングを確認すると以下のようになっています。
![スクリーンショット 2019-09-02 12.53.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475098/0e91bee8-3f70-703a-ac6b-4bb7d080003a.png)
コントローラーとビューの設定も。

```ruby:comments_controller.rb
class CommentsController < ApplicationController

# ---中略--- #

  def destroy
    Comment.find(params[:id]).destroy
    redirect_to tweets_path
  end
end
```

```ruby:/tweets/show.html.erb

# ---中略--- #

<% @comments.each do |comment| %>
  <p><span>コメント内容: </span><%= comment.body %></p>
  <p><%=link_to "削除", comment_path(comment.id), method: :delete %></p>
<% end %>
```
このようにしたら無事、コメントの削除をすることができました。
#まとめ
ルーティングをネストしてしまったら取れなくなっていしまう値があるとは考えにくいが、上手くいかなかった。
何かアドバイスがあれば教えていただきたいです。

#変更点
9/2
こちらの問題にアドバイスを頂きまして、解決いたしましたので記述します。

問題点は次の2つでした。

- `tweet_comments_path`ではなく`tweet_comment_path`
- ルーティングをネストしている場合は引数2つ必要

DELETEならs不要みたいですね。

```ruby:/tweets/show.html.erb
# ---中略--- #

<% @comments.each do |comment| %>
  <p><span>コメント内容: </span><%= comment.body %></p>
  <p><%=link_to "削除", tweet_comment_path(comment.tweet.id, comment.id), method: :delete %></p>
<% end %>>
```

```ruby:comments_controller.rb
class CommentsController < ApplicationController

# ---中略--- #

  def destroy
    Comment.find_by(id: params[:id],tweet_id: params[:tweet_id]).destroy
    redirect_to tweets_path
  end
end
```
```ruby:routes.rb

# ---中略--- #

  resources :tweets do
    resources :comments, only: [:create, :destroy]
  end
```
これでうまくいきました。