[Rails] 掲示板に編集&削除機能を実装しよう

学習記録

はじめに

掲示板に編集と削除機能を実装していきます。自分が作成した掲示板のみに、編集、削除ボタンを表示させるようにしましょう。

  • 掲示板一覧画面、掲示板詳細画面にそれぞれ、編集ボタンと削除ボタンを実装しましょう。
  • 編集ボタン、削除ボタンは、掲示板を作成した本人にしか表示されないようにしましょう。
  • 削除ボタンをクリック後、確認アラートが表示され、その後「はい」をクリックすることで削除されるようにしましょう。
  • 編集ページと新規作成ページのフォームは共通のパーシャルを使って共有させましょう。
  • コントローラの各アクションで重複する処理は、まとめて記載するようにしましょう。
  • 直接URLから他人の作成した掲示板の編集ページにアクセスした場合、404エラーが表示されるようにしましょう。

必要な作業

  • ルーティングの設定
  • コントローラの設定
  • ビューファイルの設定

ルーティングの設定

edit, update, destroyアクションを追加します。

Rails.application.routes.draw do
	resources :boards, only: %i[index new create show edit update destroy] do
		resources :comments, ojnly: %i[create], shallow: true
end

結局、resorcesすべてのアクションを使うことになりましたので、only: %i[index new create show edit update destroy]は不要ですね。

Rails.application.routes.draw do
	resources :boards do
		resources :comments, ojnly: %i[create], shallow: true
end

コントローラの設定

class BoardsController < ApplicationController
 before_action :set_board, only: %i[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 set_board
    @board = current_user.boards.find(params[:id])
  end

  def board_params
    params.require(:board).permit(:title, :body, :board_image, :bord_image_cache)
  end

コードを紐解く

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

edit, update, destroy アクションでは、他人の作成した掲示板を変更できないようにcurrent_userを介して掲示板を取得しましょう。

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

redirect_to @board, success: t('defaults.message.updated', item: Board.model_name.human)

redirect_to @board で掲示板詳細画面に遷移します。

これは、redirect_to board_path(@board) の省略形であると、Railsが良しなに解釈してくれています。


@board.destroy!

なぜ ! を付けているのでしょうか?

destroydestroy! の違いは、削除に失敗した場合の振る舞いにあります。

前者はfalse を返し、後者は例外を発生させます。

今回の場合だと、「掲示板を削除する」という行為が失敗する事を想定していません。

ですから、destroy! と記載して、万が一処理に失敗した場合は、システムエラーとして処理を中断させて、おかしな挙動のまま機能を使わせないようにしています。


ビューファイルの設定

編集ボタン、削除ボタンの実装

編集のリンクを、掲示板編集画面へ遷移するようにパスを変更します。

削除リンクを、パスを変更、確認アラートが表示されるように記述を追加します。

<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>

掲示板一覧画面、掲示板詳細画面にボタンを表示

<%= render 'crud_menus', board: board if current_user.own?(board) %>
<%= render 'crud_menus', board: board if current_user.own?(board) %>

掲示板編集画面のビューを作成します。

掲示板新規作成画面のビューとほとんど同じなのでコピーしてきます。

content_for の部分だけ、掲示板詳細画面と同じく個別のタイトルが出力されるように変更しておきましょう。

<% 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>

国際化対応

ja.ymlファイルに、メッセージを追記しておきましょう。

ja:
  defaults:
    message:
      updated: "%{item}を更新しました"
      not_updated: "%{item}を更新できませんでした"
      deleted: "%{item}を削除しました"
      delete_confirm: '削除しますか?'
  boards:
    edit:
      title: '掲示板編集'

おわりに

今回の学習では以下の要点をしっかりマスターしておきましょう。

  • data-confirmによるアラートの表示の仕方
  • create, create!の違い(破壊的メソッド)
  • 他人の掲示板を編集・削除しようとした際の制御(Boardでなくcurrent_user.boardsから取得)

参考記事

コメント

タイトルとURLをコピーしました