【初心者向け🔰】Ruby on Rails チュートリアル 入門（データ更新・削除画面を作る）

## 概要
初めて 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 のデータを画面に表示する](https://qiita.com/to3izo/items/422e06724f360e1d0d19)|
|#5|[画面から DB にデータを登録する](https://qiita.com/to3izo/items/7d3c5a532e129bfd3a0a)|
|#6|**画面から DB のデータをの更新・削除する**（今回）|

### 対象
- 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

## 手順（データ更新画面を作る）
データ更新処理を作る場合、アクションは `edit`（フォーム入力・エラーチェック） と `update`（データ更新） の２つを使って実現する。

### ルーティング追加
```diff_ruby:config/routes.rb
   Rails.application.routes.draw do
     root "users#index"

     get "/users", to: "users#index"
     get "/users/new", to: "users#new"
     get "/users/:id", to: "users#show", as: "user"
     post "/users", to: "users#create"
+    get "/users/:id/edit", to: "users#edit"  # 追加
+    patch "/users/:id", to: "users#update"  # 追加
   end
```

### 更新用のアクションを追加する
コントローラに `edit` アクションと `update` アクションを以下の様に追加する。

```diff_ruby:app/controllers/users_controller.rb
 class UsersController < ApplicationController

+   def edit
+     @user = User.find(params[:id])
+   end

+   def update
+     @user = User.find(params[:id])
+
+     if @user.update(user_params)
+       redirect_to @user
+     else
+       render :new, status: :unprocessable_entity
+     end
+   end

    private
      :
  end
```
👉 `edit` アクションで事前に特定の `id` のデータを取得し、画面に渡す。その後、`update` アクションで、同じデータに対して入力された内容で上書きを実行する。
👉 更新成功後のリダイレクトと、バリデーションエラー時の動きは、登録画面と同じになる。

### 更新画面を作る…その前に
データ更新画面とデータ登録画面は、入力フォームの画面構造がほぼ同じになる。
違う点は、「画面のタイトル名」と「あらかじめ入力エリアに値があるか無いか」だけ。
そのため、**"DRYの原則"** から、入力フォーム部分は共通部品にすべきなので、**パーシャル（＝部分的な）テンプレート** にして、登録画面と更新画面で共有するように変える。


### パーシャルテンプレートを作る

::: note warn
パーシャルな画面ファイルを作成する場合、必ずファイル名の先頭は `_` から始めなければならないルールになっている。
:::

登録画面とほぼ同じ内容で、以下のパーシャルテンプレートを用意する。

```erb:app/views/users/_form.html.erb
<%= form_with model: user do |form| %>
  <div>
    <%= form.label :name %><br>
    <%= form.text_field :name %>
    <% user.errors.full_messages_for(:name).each do |message| %>
      <div><%= message %></div>
    <% end %>
  </div>

  <div>
    <%= form.label :age %><br>
    <%= form.text_field :age %>
    <% user.errors.full_messages_for(:age).each do |message| %>
      <div><%= message %></div>
    <% end %>
  </div>

  <div>
    <%= form.submit %>
  </div>
<% end %>
```
👉 登録画面と異なる点は 変数に `@user` を使わず `user` としている点。これは、共通部品なので、特定のインスタンス変数を利用するような書き方をすると、うまく動かなくなるため。

### 登録画面を修正する
登録画面を、パーシャルを使った画面に修正する。テンプレートの中身は以下のみの状態になる。

```erb:app/views/users/new.html.erb
<h1>New User</h1>

<<%= render partial: "form", locals: { user: @user } %>
```
👉 タイトル以外はパーシャル化してスッキリ。
👉 `ender partial: "form"` は `_form.html.erb` をレンダリングする指定。
👉`locals: { user: @user }` は 変数 `@user` を **ローカル変数: user** としてパーシャル画面に渡している。

### 更新画面を作成する
`edit.html.erb` を作成し、登録画面と同様の更新画面を用意する。

```erb:app/views/users/edit.html.erb
<h1>New User</h1>

<<%= render partial: "form", locals: { user: @user } %>
```

### 詳細画面に修正ボタンを追加する
修正ボタンを、詳細画面の適当な場所に追加する。

```diff_erb:app/views/users/show.html.erb
+  <div>
+    <%= button_to "修正", { action: "edit" }, method: :get %>
+  </div>

   <%= link_to '一覧', users_path %>
```

### 画面完成、動作確認

実際に編集ができるか試してみる。
![rails_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/29498e69-7ddb-05b1-2d94-5cb75137e4f7.png)

更新画面に遷移すると、事前に値がセットされている。
![rails_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/97386d62-d13c-ff2d-e30e-84fc1aa70463.png)

これで、編集画面は完成👏✨

## 手順（データ削除画面を作る）
データ更新処理を作る場合、アクションは `delete` のみ。

### ルーティング追加
```diff_ruby:config/routes.rb
   Rails.application.routes.draw do
     root "users#index"

     get "/users", to: "users#index"
     get "/users/new", to: "users#new"
     get "/users/:id", to: "users#show", as: "user"
     post "/users", to: "users#create"
     get "/users/:id/edit", to: "users#edit"
     patch "/users/:id", to: "users#update"
+    delete "/users/:id", to: "users#destroy"  # 追加
   end
```

### 削除アクションを追加する
コントローラに `delete` アクションを以下の様に追加する。

```diff_ruby:app/controllers/users_controller.rb
+  def destroy
+    @user = User.find(params[:id])
+    @user.destroy
+
+    redirect_to root_path, status: :see_other
+  end
   :
   private
```
👉 削除後、ブラウザを HTTP ステータスコード `303: See Other` でトップページにリダイレクトさせる。

### 詳細画面に修正ボタンを追加する
修正ボタンを、詳細画面の適当な場所に追加する。

```diff_erb:app/views/users/show.html.erb
   <div>
     <%= button_to "修正", { action: "edit" }, method: :get %>
+    <%= button_to "削除", "/users/#{@user.id}", method: :delete %>
   </div>

   <%= link_to '一覧', users_path %>
```

### 画面完成、動作確認

実際に編集ができるか試してみる。
![rails_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/b633fefc-e79f-d30b-7dc1-bf32b47efe8a.png)

無事に削除して一覧画面に戻れば、実装完了👏✨

## まとめ

- 共通部品化できるものは、パーシャルテンプレートにする
- 更新処理は `edit` アクションと `update` アクションを使用する
- 削除処理は `destroy` アクションを使用する
- 画面も処理も、共通部品を増やして利用すると便利

今回で、アプリ開発としての最低限の部分は解説完了とします。
細かい点は、別の記事で解説をしていきます🙋‍♂️✨