3-13. 詳細ページを表示しよう

# 今回の学習
3-1. ターミナル（コマンドプロンプト）の使い方
3-2. Ruby on Rails について
3-3. データベースの構造を理解しよう
3-4. MVCの基本を学ぼう
3-5. ページ遷移を実装しよう
3-6. Railsの構成について
3-7. モデルとマイグレーションについて
3-8. 投稿ページを表示しよう
3-9. ツイートを投稿しよう
3-10. 投稿機能おさらい前編 -投稿ページにフォームを表示する
3-11. 投稿機能解説おさらい後編 -フォームから送信された情報を保存する
3-12. 一覧ページを表示しよう
<font color="red"><b>3-13. 詳細ページを表示しよう</b></font>
3-14. ツイートを編集しよう
3-15. ツイートを削除しよう


# はじめに

今回はツイートの詳細ページを作ります。
一覧ページに並んでいるツイートをクリックすると、そのツイートに関する詳細が見られるページというイメージです。

<img src="https://bit.ly/3zrkMgP" alt="3-13-1.gif"/>



# 概要

実装は、「ルーティング、アクション、ビュー」の順に行います。

`tweet#show`アクションへのルーティングを実装したら、
アクション内でパス内の`id`情報を使って、対応する`id`のツイート情報をデータベースから取得します。
次にビューの方で取得したツイートの各種情報を表示します。

また、一覧ページから詳細ページに遷移できるように、リンクも用意しなければなりません。
これは`link_to`を使って実装します。

それでは作っていきます。

# ▼▼▼実装&解説動画

<iframe src="https://player.vimeo.com/video/586365384#t=50m38s"  width="640" height="382" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen class="iflame"></iframe>

# 実装

## ルーティング
```ruby:config/routes.rb
Rails.application.routes.draw do
#割愛
  get 'tweets/:id' => 'tweets#show',as: 'tweet'

end
```

`as: ~`という見慣れない表現が出てきました。
詳細な説明は割愛しますが、これは`tweets#show`に遷移するためのパスを`tweet`に明示的に指定するための記述です。
今は「ヘぇ〜、そうなんだ〜」くらいに思ってくれれば大丈夫です。
できたルーティングを確認します。

```sh:ターミナル
$ rails routes
```

<img src="https://bit.ly/3kgnO1M" alt="3-13-1.png"/>


`tweets#show`というアクションを作りました。

`tweets#show`は`GET`メソッドでアクセスしているので、**単にページを表示するだけのアクション**です。

パス（`URI Pattern`)をみてみると、`tweets/:id`という書き方になっています。
パスの中に`:`(コロン)がついてるとき、その文字列は`変数`として認識されます。
今回の場合だと`tweets/:id`となっているため`:id`が変数となります。
これにより、`:id`の部分に入った文字を、アクションの中で`params[:id]`と入力することによって受け取れるようになります。
例えば`tweets/123`というページにアクセスすると、`params[:id]`で`123`を受け取れます。
今はイマイチ理解できなくても、コードを書きながら手に馴染ませて理解を深めていきましょう。

…

Railsでは、あるアクションで定義された変数を別のアクションで使うことはできません。アクションはそれぞれ互いに無関係に実行されます。
`tweets#show`アクションでも、データベースからツイートのデータを取ってくる必要があります。

続いて`tweets#show`アクションを実装します。

## 詳細ページ表示 - tweets#show

### コントローラー - tweets_controller.rb

以下のようにshowアクションを定義します。privateより上側に書きましょう。

```ruby:tweets_controller.rb
class TweetsController < ApplicationController
  def index
    @tweets = Tweet.all
  end

  def new
    @tweet = Tweet.new
  end

  def create
    tweet = Tweet.new(tweet_params)
    if tweet.save
      redirect_to :action => "index"
    else
      redirect_to :action => "new"
    end
  end

  # 追記ここから
  def show
    @tweet = Tweet.find(params[:id])
  end
  # ここまで

  private
  def tweet_params
    params.require(:tweet).permit(:body)
  end
end
```

`@tweet`という変数に、送られてきた`id`のツイートの情報を代入しています。


### ビュー - show.html.erb

さきほど用意した`@tweet`をつかって詳細ページを表示します。
まずはapp/views/tweetsの階層に`show.html.erb`ファイルを作成してください。

<img src="https://bit.ly/3sJqj0h" alt="3-13-2.png"/>

続いて以下のようなコードを記入してください。

```erb:show.html.erb
<h1>GeekTwitter</h1>
<h3>Tweet詳細</h3>
<div class="tweet">
  <p><%= @tweet.body %></p>
  <p><%= @tweet.created_at %></p>
</div>

<%= link_to "Tweet一覧に戻る", tweets_path %>
```

ツイートの内容と作成日時を表示しています。



## 一覧ページ表示 - tweets#index

コントローラーの中身は変更しませんが、
詳細ページへのリンクを表示するためにビューファイルを変更します。
`<%= link_to "詳細へ", tweet_path(t.id) %>`の一行を
`<% @tweets.each do |t| %>` ~~ `<% end %>`の間に追加します。

### ビュー - index.html.erb

```erb:index.html.erb
<h1>GeekTwitter</h1>
<h3>Tweet一覧</h3>
<%= link_to "新規投稿へ", tweets_new_path %>
<div class="tweets-container">
  <% @tweets.each do |t| %>
  <div class="tweet">
    <%= t.body %>
    <%= t.created_at %>
     #追記始め
    <%= link_to "詳細へ", tweet_path(t.id) %>
　　 #追記終わり
  </div>
  <% end %>
</div>

```

# 確認

```sh:ターミナル
$ rails s
```

一覧ページ（`localhost:3000`）にアクセスみましょう！

前回ツイートを投稿していたら、その詳細ページへのリンクが追加されているはずです。
それをクリックすると…

<img width="363"  src="https://bit.ly/3klSC15" alt="3-13-3.png"/>

以上のようになったでしょうか？


# 解説


## 詳細ページ表示 - tweets#show


### コントローラー - tweets_controller.rb

```ruby:tweets_controller.rb
class TweetsController < ApplicationController
  # 割愛

  def show
    @tweet = Tweet.find(params[:id])
  end

  private
  # 割愛
end
```

`tweets#show`アクションでは、まず**一覧ページから送られてきた`id`に対応するツイートをデータベースから取得**します。

ここで各ツイートはそのツイート固有の番号が`id`カラムに保存されています。
実際私たちはtweetsテーブルを作成する際にidカラムは作成していませんでしたが、このカラムはRailsがデフォルトで作成してくれ、新しいツイートが保存される毎に新しい番号をツイートに割り振ってくれています。

<img src="https://bit.ly/3sKJsiH" alt="3-13-4.png"/>


ツイートを`id`で検索して取得するには、Railでもともと定義されている`find`メソッドを使います。
以下は`id`が１のツイートの情報を取得するコードです。

```ruby:
Tweet.find(1)
```

今回は、検索するツイートの`id`は`params[:id]`に入っている数字を使うので、以下のようになります。

```ruby:
Tweet.find(params[:id])
```

<img src="https://bit.ly/3B6rbPG" alt="3-13-5.png"/>

まとめると、パスに含まれる`:id`を`params[:id]`で受け取り、その`id`に対応するツイートの情報を探し、それをビューファイルの中で扱えるように`@tweet`に代入しています。

![スクリーンショット 2022-11-23 4.52.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851197/7d4c7071-e3f2-d495-4bb0-bca1302f3d49.png)
↑ idが2のツイートを表示

![スクリーンショット 2022-11-23 5.05.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851197/750b51da-68b5-1c50-c80b-fa145014e5a9.png)

idが2のツイートをデータベースのtweetsテーブルから持ってきています。


## 一覧ページ表示 - tweets#index

```erb
<%= link_to "詳細へ", tweet_path(t.id) %>
```


`link_to`を使って一覧ページから詳細ページに遷移できるようにしています。

これまでの`link_to`と違うところは、`〇〇_path`の後に`(t.id)`があることです。

`tweet_path(t.id)`と書くことで、`:id`に`t.id`を埋め込んだ`tweet_path`を作成してくれます。
このおかげでshowアクションの`params[:id]`に必要なidを送ることができます。

<h1>ソースコードの確認</h1>
最後にGithubでソースコードを確認しましょう！
エラーが出てる方は、下記のURLにアクセスしてソースコードに間違いがないか確認しよう！
確認する場合は下のGithubをクリック！

<a href="https://github.com/kakeruAoyama/geektwitter/commit/d193a0854fa8971d9a84be669d2690d98c0f9ed1" target="_blank"><img width = 100  src="https://bit.ly/3kkWu2p" alt="3-4-16.png"/></a>	

# クイズ

①ツイートをidで検索して取得するには、Railでもともと定義されている ? メソッドを用いる
<details><summary>答え</summary>
find
</details>



②詳細に飛ぶためのリンクを作るコードは？
<details><summary>答え</summary>
<%= link_to "詳細へ", tweet_path(t.id) %>
</details>



# おわりに

<img src="https://bit.ly/39juNCb" alt="3-13-2.gif"/>

以上で詳細ページの実装は完了です！お疲れ様でした！！！

# 記録フォームの送信
ここまでお疲れ様です！
最後にみなさんが本記事をいつ終えたか記録すること、また本記事をさらにいいものにするために以下のフォームに記入いただけると嬉しいです！

<a href="https://forms.gle/SfcGHScXNBivKwEQ9" target="_blank">アンケートフォーム</a>	

[<img src="https://bit.ly/3kiSzTH" alt="UIUX.jpeg"/>](https://qiita.com/suzuxtuti5/private/67e92653884d59698319)
[<img src="https://bit.ly/3ybakJz" alt="VE.png"/>](https://qiita.com/GeekSalon/private/e2c32481976acdc3f6ca)