【初心者向け🔰】Ruby on Rails チュートリアル 入門（DB のデータを画面に表示する）

## 概要
初めて Ruby on Rails で Web アプリ開発するための、入門編の記事。
Rails の基礎部分をなるべく絞って解説する。

|手順|記事|
|---|---|
|#1|[Rails の開発環境構築](https://qiita.com/to3izo/items/5d06243998192513bed9)|
|#2|[コントローラ・ビューの基本](https://qiita.com/to3izo/items/697497daf7c4722e98d3)|
|#3|[モデルとマイグレーションの基本](https://qiita.com/to3izo/items/a17a6ce61e0002fd8f5c)|
|#4|**DB のデータを画面に表示する**（今回）|
|#5|[画面から DB にデータを登録する](https://qiita.com/to3izo/items/7d3c5a532e129bfd3a0a)|
|#6|[画面から DB のデータをの更新・削除する](https://qiita.com/to3izo/items/a8001c1bbf7919d137ed)|

### 対象
- Ruby on Rails で開発をしてみたい（しなければならない状況になった）方
- HTML/CSS で簡単な Web ページを書いたことがある方
- 「DB」「SQL」という言葉の意味を何となく理解できる方
- 「REST API」や「GET」「POST」などを聞いたことがある方
- Ruby もしくは、その他のオブジェクト指向のプログラミング言語に触れた方
  - 変数、四則演算、if 文、for 文、などは書いたことある
  - クラス、メソッド、インスタンス、などは聞いたことある

### 前提
:::note warn
macOS で作業する前提で書いてます。Windows の方は適宜、読み替えてください🙏
:::

- OS： macOS 13.12.1 "Ventura"
- CPU： Intel
- Ruby： v3.1.3
- SQLite3： v3.39.5
- Bundler： v2.4.9
- Rails： v7.0.4

## アクションの命名規約
Rails のアクション名は自由に設定可能だが、「基本的にこういうアクション名にしましょう」という規約がある。

|アクション名|役割|
|---|---|
|index|リソースの一覧を表示する|
|new|リソースを新規作成する|
|create|リソースを新規作成して追加(保存)する|
|edit|リソースを更新するためのフォームを作成する|
|show|レコードの内容（詳細）を表示する|
|update|リソースを更新する|
|destroy|リソースを削除する|

## 手順（DB データを一覧表示する画面を作る）
[前回の記事](https://qiita.com/to3izo/items/a17a6ce61e0002fd8f5c) までで作成したアプリケーションと DB データを利用します。

前回作成した「users テーブル」のデータ

|id|name|age|
|---|---|---|
|1|佐藤|17|
|2|鈴木|21|

### Users ルーティング追加
User モデルに合わせて、**/users** というルーティングを追加する。

```diff_ruby:config/routes.rb
Rails.application.routes.draw do
    get "/", to: "top#index"
+   get "/users", to: "users#index"
end
```

:::note warn
Rails では、「（主に）一要素を扱う」観点から、モデルは **"単数系"** で命名するが、コントローラや DB テーブル等は「要素の集まりを扱う」観点から **"複数形"** で命名するルールになっている（前記事の Top コントローラは例外な書き方）。
:::

### Users コントローラを新規作成
こちらも User モデルに合わせて、Users のコントローラを新規作成する（ルーティングの追記はオプションでスキップ）。

```zsh
rails g controller Users index --skip-routes
```

生成されたコントローラに、 **User モデル** を使って **users テーブル** のデータを全件取得し、変数にセットする処理を追記する。

```diff_ruby:app/controllers/users_controller.rb
class UsersController < ApplicationController
  def index
+   # users テーブルからレコード全件取得
+   @users = User.all
  end
end
```

### 画面テンプレート作成
取得したデータを一覧表示するように、画面テンプレートを以下の様に全て修正する。

```erb:app/views/users/index.html.erb
<h1>Users</h1>

<ul>
  <% @users.each do |user| %>
    <li>
      <%= user.name %> / <%= user.age %>
    </li>
  <% end %>
</ul>
```

### 画面で一覧表示
Rails サーバを起動して、ブラウザで `localhost:3000/users` にアクセスする。
![rails_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/913f8481-2444-def6-9a3f-3fe46e622ea5.png)

## 手順（1 件のデータのみ表示する詳細画面を作る）
次は、複数のデータの中から、1 件だけ抽出して表示する画面を追加する。

### ルーティングを追加する

```diff_ruby:config/routes.rb
Rails.application.routes.draw do
    get "/", to: "top#index"
    get "/users", to: "users#index"
+   get "/users/:id", to: "users#show"
end
```
👉 `:id` は、**パスパラメータ（Path parameter）** を意味する。この部分に数値や文字列などが当てはめられた場合、ルーディングに設定されたアクションで `params[:id]` 形式でその値を取得できる。
👉 今回の場合、 `/users/1` にアクセスされた場合、**Users コントローラ** の **show メソッド** の中で、`params[:id]` と指定すると「 1 」が取得できることになる。

### 既存コントローラにアクションを追加する
Users コントローラに、ルーティングに設定した **show アクション** を追加する

```diff_ruby:app/controllers/users_controller.rb
class UsersController < ApplicationController
    def index
      @users = User.all
    end

+   # アクション追加
+   def show
+     @user = User.find(params[:id])
+   end
end
```

### 画面テンプレート作成
`index.html.erb` と同じディレクトリに `show.html.erb` を追加する

```erb:app/views/users/show.html.erb
<h1>User Detail</h1>

<ul>
  <li> ID：<%= @user.id %> </li>
  <li> 名前：<%= @user.name %> </li>
  <li> 年齢：<%= @user.age %> </li>
  <li> 作成日：<%= @user.created_at %> </li>
  <li> 更新日：<%= @user.updated_at %> </li>
</ul>
```

### 画面で一覧表示

ブラウザで `localhost:3000/users/1` にアクセスする。
![rails_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/61f29e96-d222-2766-6bf6-977a8b1ca8d6.png)
👉 DB の users テーブルから `id: 1` のレコードを取得し、表示する画面ができた！

## 手順（ビューヘルパーを使ってリンクを作る）
URL 直接入力ではなく、リンクを表示して詳細画面に遷移できる様にする。
今回は、HTML の a タグではなく、Rails には用意されている「ヘルパー」という機能を活用する。
画面遷移でよく使われる「`link_to`　ヘルパー」と「URL ヘルパー」を利用する。

### ルーティングに名前をつける
show アクションのルーティングの末尾に `as` で名前を追加する。

```diff_ruby:config/routes.rb
Rails.application.routes.draw do
-   get "/users/:id", to: "users#show"
+   get "/users/:id", to: "users#show", as: "user"
end
```
👉これで、show アクションのルーティングに `user` という **「ルーティング名（ルート名）」** が付与される。

### ヘルパーを使って画面にリンクを追加する
一覧表示 `/users` の画面を以下の様に修正する

```diff_erb:app/views/users/index.html.erb
<ul>
  <% @users.each do |user| %>
    <li>
      <%= user.name %> / <%= user.age %>
+     <%= link_to '詳細', users_path(user.id) %>
    </li>
  <% end %>
</ul>
```
👉 `<%= link_to '表示する文字', リンク先 %>` で追加できる。
👉 `リンク先` 部分には「URL ヘルパー」を利用する。 `ルーティング名_path(変数)` で変数をパラメータとして渡しながら、設定したルーティングを呼び出すことができる。

### 画面確認

「詳細」というリンクテキストが表示され、クリックすると各 id の画面に遷移できる。
![rails_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/3fb3e779-1df0-a707-2460-7874acebdd8f.png)

### 詳細画面から一覧画面に戻るリンクも作る
`show.html.erb` に `link_to` ヘルパーを追加する

```diff_erb:app/views/users/show.html.erb
  <ul>
    <li> ID：<%= @user.id %> </li>
    <li> 名前：<%= @user.name %> </li>
    <li> 年齢：<%= @user.age %> </li>
    <li> 作成日：<%= @user.created_at %> </li>
    <li> 更新日：<%= @user.updated_at %> </li>
  </ul>

+ <%= link_to '一覧', users_path %>
```
👉 一覧画面の場合、ルーティングにパラメータが無いため、パスには単純に `users`が利用できる。そのため、`link_to` のリンク先には `users_path` が利用できる。

![rails_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/6af8d00b-3352-be08-653d-40ad8ebd3153.png)

### URL ヘルパーの考え方
link_to に利用する URL ヘルパーは、以下の動きになる様になっている（`users` というパスの例）。

- `users_path`： `/users` を返す
- `user_path(:id)`： `/users/:id` を返す（ただし、`user` というルーティング名の事前設定が必要）
- `new_photo_path`： `/photos/new` を返す

## まとめ

- モデルから取得した値を、コントローラで変数にセットすることで、画面でも呼び出して表示できる
- 画面のリンクには `link_to` ヘルパーが利用できる
- `link_to` のパス部分は「URL ヘルパー」が利用できる
  - URL ヘルパーについては少し混乱するため、慣れが必要