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

掲示板編集ページの作成

フォーム部分はパーシャルを用意して、新規作成ページと共有できるようにしておく ので、今回編集ページのビューは以下のようになる

#boards/edit.html.erb
<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>

現在ログインしているユーザーのidと掲示板のuser_idが同じ場合編集、削除アイコンを表示させる。まず、この判定を行うメソッドをuserモデルのインスタンスメソッドとして記述しておく

#user.rb
def own?(object)
    id == object.user_id
end

ビューに直接ifなどを使って判定してもいいが、userモデルに判定のロジックを記載することで、ロジックを見直したりしたいときなどにuserモデルを見るだけで済む。また引数にobjectを受け取るようにすることで、掲示板だけでなく、コメントなどユーザーに他の関連づいたインスタンスの判定も行えるようにしている。 ビューはこのメソッドを使うことで以下のようになる

<% if current_user.own?(board) %>
      <%= link_to edit_board_path(board), id: 'button-edit-#{board.id}' do %>
         <%= icon 'fa', 'pen' %>
      <% end %>
      <%= link_to '#', id: 'button-delete-#{board.id}', method: :delete, data: {confirm: ''} do %>
         <%= icon 'fas', 'trash' %>
      <% end %>
  <% end %>

edit,update,destroyアクションの作成 先にコードを記載すると以下のようになる

  before_action :set_board, only: %i[edit update destroy]
  def edit; end

  def update
    if @board.update(board_params)
      redirect_to board_path(@board), success: t('.success')
    else
      flash.now[:danger] = t('.fail')
      render :edit
    end
  end

  def destroy
    @board.destroy!
    redirect_to boards_path, success: t('.success')
  end

  private

  def set_board
    @board = current_user.boards.find(params[:id])
  end

今回は,edit,update,destroyアクションにおいて、ルーティングのboardオブジェクトのidから現在のユーザーに関連付いたBoardオブジェクトを取得してプロセスが共通なので、コールバック(オブジェクトに対して、特定のアクションを実行した瞬間に呼び出されるメソッドのこと)としてprivateに登録してある。
privateに登録するのは記載したクラスの外から呼び出されて、悪用されるのを防ぐため
before_action :set_board, only: %i[edit update destroy]の記述によりedit,update,destroyアクションの実行前にset_boardアクションが実行される

確認ダイアログの表示

削除アイコンは

<%= link_to board_path(board), id: 'button-delete-#{board.id}', method: :delete, data: {confirm: ‘よろしいですか?’} do %>

と記述method: :deleteによってHTTPにDELETEリクエストを発行してくれるこの時 HTTPはDELETEリクエストを受け取ることができないので,Rails側はJavascriptを使って偽造してくれる。つまりjavascriptがオフになっていると削除のリンクも無効になってしまうということ。また、リンクやフォームにdata-confirm属性を追加することで、確認ダイアログを表示してくれる。confirm: に表示したい文字列を追加する
また、destroyアクションでdestroyメソッドではなくdestroy!メソッドを使っているのはデータを削除するとき失敗する想定(バリデーションなど)に引っかかるなどを今回の仕様では想定していないため、万が一削除の処理に失敗した場合には処理を中断させて例外として扱う必要があるためである。

参考文献

Active Record の基礎 - Railsガイド

Active Record コールバック - Railsガイド

Rails で JavaScript を使用する - Railsガイド