Rails 掲示板の編集、削除機能の実装　解説

#コントローラーに編集と削除を追加
###ルーティングの設定

```rb:config/routes.rb
Rails.application.routes.draw do
  root 'static_pages#top'

  get 'login', to: 'user_sessions#new'
  post 'login', to: 'user_sessions#create'
  delete 'logout', to: 'user_sessions#destroy'

  resources :users, only: %i[new create]
  resources :boards do
    resources :comments, only: %i[create], shallow: true
  end
end
```
・前回はonly: %i[index new create show] で、４つ指定したいたが今回は「destroy」「edit」「update」を加えるのでonlyで範囲を指定をしない。

###boardコントローラーの設定

```rb:app/controllers/boards_controller.rb
class BoardsController < ApplicationController
  before_action :find_board, only: [:edit, :update, :destroy]

(略)
  def edit; end

  def update
    if @board.update(board_params)
      redirect_to @board, success: t('defaults.message.updated', item: Board.model_name.human)
    else
      flash.now['danger'] = t('defaults.message.not_updated', item: Board.model_name.human)
      render :edit
    end
  end

  def destroy
    @board.destroy!
    redirect_to boards_path, success: t('defaults.message.deleted', item: Board.model_name.human)
  end
  private

  def find_board
    @board = current_user.boards.find(params[:id])
  end
```
```rb:
before_action :set_board, only: %i[edit update destroy]
```
「edit(編集画面の表示)」「update（更新処理）」「destroy（削除処理）」アクションでは投稿を基に行う作業として共通しているので、「before_action」でまとめている。
＊before_actionはコントローラー内の全てのアクションが実行される前に、その後に続くメソッド（ここではfind_board）が実行される.

```rb:
@board = current_user.boards.find(params[:id])
```

urlのパラメーターから受け取った投稿（params[:id]）を取得して,その中にある外部キー「user_id」にログインしているユーザー（current_user）のidを代入している。これによって投稿と投稿したユーザーが一致しているのかを検証してくれる。＊user_idを取得するのが大事

```rb:
@board.update(board_params)
```
updateメソッドで更新処理を行なっている。

```rb:
redirect_to @board
```

redirect_to board_path(@board)の省略。投稿詳細ページに飛ぶ。

```rb:
 @board.destroy!
```
destroyメソッドで投稿を削除している。
＊destroyとdestroy!メソッドの違いは処理後の挙動。destroyだと失敗した後に「処理が失敗しました」などのエラー目セージを入れたり、renderを使って前画面に戻したりできる。しかし削除処理に失敗するという可能性がないので「destroy!」を使って処理をさせ、万が一処理に失敗をしてもエラー画面を出し処理を中断させる。(予想外な動きをさせない様に)

#編集・削除ボタンの実装

```rb:app/views/boards/_crud_menus.html.erb
<ul class='crud-menu-btn list-inline float-right'>
  <li class="list-inline-item">
    <%= link_to edit_board_path(board), id: "button-edit-#{board.id}" do %>
      <%= icon 'fa', 'pen' %>
    <% end %>
  </li>
  <li class="list-inline-item">
    <%= link_to board_path(board), id: "button-delete-#{board.id}", method: :delete, data: { confirm: t('defaults.message.delete_confirm') } do %>
      <%= icon 'fas', 'trash' %>
    <% end %>
  </li>
</ul>
```

#詳細画面と一覧画面にボタンを表示

```rb:app/views/boards/show.html.erb
 <%= render 'crud_menus', board: @board if current_user.own?(@board) %>
```

```rb:app/views/boards/_board.html.erb
<%= render 'crud_menus', board: board if current_user.own?(board) %>
```
・パーシャルの'crud_menus'を呼び出し、model: boardに＠boardを代入している。
・「if current_user.own?(@board)」はuserモデルで作成した「own?(object)」メソッドを使っている。
＊「curremt_user」のidと「＠board」のuser_idが一致を検証している。これがあることでログインしているユーザーと投稿作成した人が同じかを確認している。

```rb:
  def own?(object)
    self.id == object.user_id #selfは省略できる
  end
```

#掲示板編集のビューを追加

```rb:app/views/boards/edit.html.erb
<% content_for(:title, @board.title) %>
<div class="container">
  <div class="row">
    <div class="col-lg-8 offset-lg-2">
      <h1><%= t('.title') %></h1>
      <%= render 'form', { board: @board } %>
    </div>
  </div>
</div>
```

```rb:
<%= render 'form', { board: @board } %>
```

・投稿フォームのパーシャル（app/views/boards/_form.html.erb）を呼び出している。{ board: @board }の「board」に、「find_board」アクションの中の「 @board = current_user.boards.find(params[:id])」の＠boardを代入している。これにより、urlのパラメーターから編集する投稿を取得している。