1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

Posted at

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

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] で、4つ指定したいたが今回は「destroy」「edit」「update」を加えるのでonlyで範囲を指定をしない。

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

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
before_action :set_board, only: %i[edit update destroy]

「edit(編集画面の表示)」「update(更新処理)」「destroy(削除処理)」アクションでは投稿を基に行う作業として共通しているので、「before_action」でまとめている。
*before_actionはコントローラー内の全てのアクションが実行される前に、その後に続くメソッド(ここではfind_board)が実行される.

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

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

@board.update(board_params)

updateメソッドで更新処理を行なっている。

redirect_to @board

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

 @board.destroy!

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

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

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>

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

app/views/boards/show.html.erb
 <%= render 'crud_menus', board: @board if current_user.own?(@board) %>
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が一致を検証している。これがあることでログインしているユーザーと投稿作成した人が同じかを確認している。

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

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

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>
<%= render 'form', { board: @board } %>

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

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?