【Ruby on Rails】初学者向け－開発の流れについて④　一覧、新規作成、参照、更新、削除画面機能の追加編vol.2

## Rails開発の流れについて

・Railsプロジェクトの作成とDockerの設定
[【Ruby on Rails】初学者向け－開発の流れについて①　プロジェクトの作成編](https://qiita.com/y-kida/items/2c8634ceb28a93c84bc9 "Qiita Home")

・Gem・DB設定とルーティング
[【Ruby on Rails】初学者向け－開発の流れについて②　Gem・DB設定とルーティング編](https://qiita.com/y-kida/items/1d34bf72a3296579f213 "Qiita Home")

・Bootstrapの導入
[【Ruby on Rails】初学者向け－開発の流れについて③　Bootstrapの導入編](https://qiita.com/y-kida/items/cb3723a344766fcaf15e "Qiita Home")

・一覧、新規作成、参照、更新、削除画面機能の追加vol.1
[【Ruby on Rails】初学者向け－開発の流れについて④　一覧、新規作成、参照、更新、削除画面機能の追加vol.1](https://qiita.com/y-kida/items/2d5edbe3be1cd7b7289c "Qiita Home")

**・一覧、新規作成、参照、更新、削除画面機能の追加vol.2（今回学習するのはこちら）**
・検索機能の追加
・DBやモデル周りの整備
・バリデーション機能追加
・ユーザー認証機能追加

（※ 他追加機能があれば随時記事にしていく予定です）

--------------------------------------------------------
**前提**
・Docker
・Ruby on Rails 7
・Mysql
・BootStrap
・VSCode

-------------------------------------------------------

**前回のおさらい**
前回は新規作成したデータを一覧画面で表示ができるように処理を記載しました。
今回はそのデータを一覧画面から選択し、参照・更新・削除が行えるようにしましょう。

<h1>参照・更新・削除について</h1>

**参照画面**

まず参照画面の作成から行います。
一覧画面から選択したデータのIDをとってきて、データの詳細を表示するという動作にしたいと思います。

最初にtasks_controller.rbのshowメソッドを記載します。
```ruby:app\controllers\tasks_controller.rb
    # ~~~~~~~~省略~~~~~~~~~
    def show
        @task = Task.find(params[:id])
    end
    # ~~~~~~~~省略~~~~~~~~~
```

参照画面を増やすのでroutes.rbへの追記も必要です。
```ruby:config\routes.rb
Rails.application.routes.draw do
  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html

  # Defines the root path route ("/")
  root "tasks#index"
  get 'tasks', to: 'tasks#index'
  get 'tasks/new', to: 'tasks#new'
  post 'tasks', to: 'tasks#create'
  # 追記
  get 'tasks/:id', to: 'tasks#show', as: 'task'
end
```

showアクションでは情報を取得して表示を行うのでGETメソッドを用います。

**as: 'task'**
…記載例でいうと、ビューやコントローラー内でtask_path(@task)やtask_url(@task)のような
　ヘルパーメソッドを使用して、このshowアクションに対するルートを簡単に参照できる
 　というもの。（直訳で「～として」という意味。つまり「task」という名前でルートが
  　使用できるようになる）


```ruby:config\routes.rb
<div class="d-flex align-items-center">
    <h1>参照画面</h1>
    <div class="ms-auto boards__linkBox">
         <%= link_to '一覧', root_path, class: 'btn btn-outline-dark'%>
    </div>
</div>
<div class="mb-3">
    <label class="form-label">タスク名</label>
    <div class="form-control">
        <%= @task.try(:title) %>
    </div>
</div>
<div class="mb-3">
    <label class="form-label">タスクの内容</label>
    <div class="form-control">
        <%= @task.try(:explanation) %>
    </div>
</div>
<div class="mb-3">
    <label class="form-label">作成日</label>
    <div class="form-control">
        <%= @task.try(:created_at).try(:strftime, '%Y年 %m月 %d日') %>
    </div>
</div>
<div class="mb-3">
    <label class="form-label">期日</label>
    <div class="form-control">
        <%= @task.try(:due_date).try(:strftime, '%Y年 %m月 %d日') %>
    </div>
</div>
```

**@task.try(:title)**
…「try」を記述してこのように取得することで、
　もしtitleの中身がnilだったとしてもエラーが発生しないようになっています。

**@task.try(:created_at).try(:strftime, '%Y年 %m月 %d日')**
…上記と同様nilだったとしてもエラーが発生しないようにしており、
　かつstrftimeで、日時を指定されたフォーマットに変換しています。

ここまで処理が記載し終わったら一覧画面から参照画面を表示してみましょう。

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3906686/12bb605c-3716-1e11-1ea1-9ca9786ff846.png)

これで参照画面が完成したので、次は更新画面の機能へ移っていきたいと思います。

**更新画面**
新規作成画面作成時に作成しておいたパーシャルがあるので、それを利用して更新画面も作成していきます。

まず、config\routes.rbに下記のように追記します。
```ruby:config\routes.rb
Rails.application.routes.draw do
  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html

  # Defines the root path route ("/")
  root "tasks#index"
  get 'tasks', to: 'tasks#index'
  get 'tasks/new', to: 'tasks#new'
  post 'tasks', to: 'tasks#create'
  get 'tasks/:id', to: 'tasks#show', as: 'task'

  # 追記
  get 'tasks/:id/edit', to: 'tasks#edit', as: 'edit_task'
  patch 'tasks/:id', to: 'tasks#update'
end
```

**patch**
…HTTPメソッドの１つ。タスクの更新を行うことができます。

次にapp\controllers\tasks_controller.rbにアクションを追加します。
```ruby:app\controllers\tasks_controller.rb
class TasksController < ApplicationController
    def index
        binding.pry
        @tasks = Task.all
    end

    def show
        @task = Task.find(params[:id])
    end

    def new
        @task = Task.new
    end

    def create
        @task = Task.new(task_params)
        if @task.save
            binding.pry
          redirect_to tasks_url, notice: '保存が完了しました。'
        else
          render :new
        end
    end

    # 追記
    def edit
        @task = Task.find(params[:id])
    end

    # 追記
    def update
        @task = Task.find(params[:id])
        if @task.update(task_params)
            redirect_to @task, notice: '更新が完了しました。'
        else
            render :edit, status: :unprocessable_entity
        end
    end

    private

    def task_params
        params.require(:task).permit(:title, :explanation, :due_date, :updated_at, :create_at)
    end

end
```

 **@task = Task.find(params[:id])**
 …edit・updateアクション内のこの記載で、idから取得した情報を＠taskに入れています。
 （この記載は、更新画面に値を表示・更新するために必要）

**if @task.update(task_params)**
…更新画面で更新ボタンを押下し、task_paramsがupdateされた場合という意味です。
　上記の例では更新成功するとメッセージが表示され、そうでない場合再び更新画面がリダイレクトされます。
 

次に更新画面のビューを作成します。
```html:app\views\tasks\edit.html.erb
<div class="d-flex align-items-center">
    <h1>更新画面</h1>
    <div class="ms-auto boards__linkBox">
         <%= link_to '一覧', root_path, class: 'btn btn-outline-dark'%>
    </div>
</div>
<!--新規作成画面同様ここでパーシャルをrenderする-->
<%= render partial: 'form', locals: { task: @task } %>
```
パーシャルについての説明はこの記事の１つ前の記事に記載しています。
[【Ruby on Rails】初学者向け－開発の流れについて④　一覧、新規作成、参照、更新、削除画面機能の追加vol.1](https://qiita.com/y-kida/items/2d5edbe3be1cd7b7289c "Qiita Home")

次に、参照画面から更新画面へ遷移できるよう、show.html.erbに以下を追記します。
```html:app\views\tasks\show.html.erb
<div class="d-flex align-items-center">
    <h1>参照画面</h1>
    <div class="ms-auto boards__linkBox">
         <%= link_to '一覧', root_path, class: 'btn btn-outline-dark'%>
    </div>
</div>
<div class="mb-3">
    <label class="form-label">タスク名</label>
    <div class="form-control">
        <%= @task.try(:title) %>
    </div>
</div>
<div class="mb-3">
    <label class="form-label">タスクの内容</label>
    <div class="form-control">
        <%= @task.try(:explanation) %>
    </div>
</div>
<div class="mb-3">
    <label class="form-label">作成日</label>
    <div class="form-control">
        <%= @task.try(:created_at).try(:strftime, '%Y年 %m月 %d日') %>
    </div>
</div>
<div class="mb-3">
    <label class="form-label">期日</label>
    <div class="form-control">
        <%= @task.try(:due_date).try(:strftime, '%Y年 %m月 %d日') %>
    </div>
</div>
<div class="mt-3">
    <!--追記-->
    <%= link_to '編集', edit_task_path(@task), class: 'btn btn-outline-dark'%>
</div>
```

ここまで記載ができたら一度、更新画面表示→編集→参照画面表示の流れでテストしてみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3906686/30524e90-02ab-f09b-3445-ac185c08e98b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3906686/91fbac4f-8a4e-3e1a-2a53-fb8960abff31.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3906686/d1aa36fe-8189-c998-3b18-046eca7cec21.png)

ここまでで問題がなければ次は削除処理について言及して行きます。

---------------------------------------------------------------------
**削除処理**
削除処理においては追加の画面を作成しません。
ただ、処理が追加されるのでルーティングは必要です。

config\routes.rbには下記のように追記します。
```ruby:config\routes.rb
Rails.application.routes.draw do
  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html

  # Defines the root path route ("/")
  root "tasks#index"
  get 'tasks', to: 'tasks#index'
  get 'tasks/new', to: 'tasks#new'
  post 'tasks', to: 'tasks#create'
  get 'tasks/:id', to: 'tasks#show', as: 'task'
  get 'tasks/:id/edit', to: 'tasks#edit', as: 'edit_task'
  patch 'tasks/:id', to: 'tasks#update'

  # 追記
  delete 'tasks/:id', to: 'tasks#destroy'
end
```

**destroy**
…特定のタスクを削除するアクションです。

次にapp\controllers\tasks_controller.rbにdestroyアクションを作成します。
```ruby:app\controllers\tasks_controller.rb
class TasksController < ApplicationController
    def index
        binding.pry
        @tasks = Task.all
    end

    def show
        @task = Task.find(params[:id])
    end

    def new
        @task = Task.new
    end

    def create
        @task = Task.new(task_params)
        if @task.save
            binding.pry
          redirect_to tasks_url, notice: '保存が完了しました。'
        else
          render :new
        end
    end

    def edit
        @task = Task.find(params[:id])
    end

    def update
        @task = Task.find(params[:id])
        if @task.update(task_params)
            redirect_to @task, notice: '更新が完了しました。'
        else
            render :edit, status: :unprocessable_entity
        end
    end

    # 追記
    def destroy
        @task = Task.find(params[:id])
        @task.destroy
        redirect_to tasks_url, notice: 'タスクが削除されました。'
    end

    private

    def task_params
        params.require(:task).permit(:title, :explanation, :due_date, :updated_at, :create_at)
    end
end
```
今回は参照画面から削除が行えるように、削除ボタンを追加しましょう。

```html:
<div class="d-flex align-items-center">
    <h1>参照画面</h1>
    <div class="ms-auto boards__linkBox">
         <%= link_to '一覧', root_path, class: 'btn btn-outline-dark'%>
    </div>
</div>
<div class="mb-3">
    <label class="form-label">タスク名</label>
    <div class="form-control">
        <%= @task.try(:title) %>
    </div>
</div>
<div class="mb-3">
    <label class="form-label">タスクの内容</label>
    <div class="form-control">
        <%= @task.try(:explanation) %>
    </div>
</div>
<div class="mb-3">
    <label class="form-label">作成日</label>
    <div class="form-control">
        <%= @task.try(:created_at).try(:strftime, '%Y年 %m月 %d日') %>
    </div>
</div>
<div class="mb-3">
    <label class="form-label">期日</label>
    <div class="form-control">
        <%= @task.try(:due_date).try(:strftime, '%Y年 %m月 %d日') %>
    </div>
</div>
<div class="mt-3">
    <%= link_to '編集', edit_task_path(@task), class: 'btn btn-outline-dark'%>
    <!--追記-->
    <%= link_to '削除', task_path(@task), 
        data: { 
            turbo_method: :delete, 
            turbo_confirm: '本当に削除しますか？'
            }, 
        class: 'btn btn-danger' %>
</div>
```

**turbo_method: :delete**
…HTTPメソッドがdeleteであることを表している。


**data: { confirm: '本当に削除しますか？' }**
…クリック時にダイアログを出して「本当に削除しますか？」のメッセージを表示する。

-------------------------------------------------------------------------

Rails7の場合、使用するJSライブラリがRails5と異なるので、
app\views\layouts\application.html.erbに以下の記載を追記する必要があります。
```html:app\views\layouts\application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title>App</title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
    <%= javascript_importmap_tags %>
    <!--追記-->
    <%= javascript_include_tag "turbo", type: "module" %>
  </head>

  <body>
    <div class="container">
    <%= yield %>
  </body>
</html>
```
--------------------------------------------------------------
ここまででデータの削除が行えるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3906686/3b38a83e-98ba-74f7-d26d-0a66b05b2468.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3906686/4530ec88-2189-ef4c-1ff0-727a8e1f54de.png)


要注意点としては、Rails7とそれ以前のバージョンでは記載方法が異なり、
場合によっては動作しないことがあります。

使用するメソッドなどにもバージョンによっては非推奨となっていることがあるため、
事前の調査が必要となります。