destroy_allの使い方(1対他モデルの一括削除)

destroy_allとは?

すでにテーブルに存在するレコードを一括で削除するメソッドです。

テーブルの状態

usersテーブル(1)にtasksテーブル(多)がhas_manyで紐付いています。

user.rbはこのようになっています。

# == Schema Information
#
# Table name: users
#
#  id              :bigint           not null, primary key
#  admin           :boolean          default(FALSE)
#  email           :string(255)
#  image           :string(255)
#  name            :string(255)
#  password_digest :string(255)
#  remember_digest :string(255)
#  created_at      :datetime         not null
#  updated_at      :datetime         not null
#
class User < ApplicationRecord
  has_many :tasks, dependent: :destroy
  accepts_nested_attributes_for :tasks, allow_destroy: true

1対多の場合は1の方(例としてuserとする)has_many :tasks, dependent: :destroyを追加記述することで、userを消したときに紐付いているtaskも削除されるようにできる!

sessions_helper.rbはこのようになっています(ほぼRailsチュートリアルと同じです)

module SessionsHelper

  # 記憶トークンcookieに対応するユーザーを返す
  def current_user
    if (user_id = session[:user_id])
      @current_user ||= User.find_by(id: user_id)
    elsif (user_id = cookies.signed[:user_id])
      user = User.find_by(id: user_id)
      if user && user.authenticated?(cookies[:remember_token])
        log_in user
        @current_user = user
      end
    end
  end

  # 渡されたユーザーがログイン済みユーザーであればtrueを返す
  def current_user?(user)
    user == current_user
  end

  # 記憶したURL (もしくはデフォルト値) にリダイレクト(フレンドリーフォワーディング)
  def redirect_back_or(default)
    redirect_to(session[:forwarding_url] || default)
    session.delete(:forwarding_url)
  end

end

task.rbはこのようになっています

# == Schema Information
#
# Table name: tasks
#  id         :bigint           not null, primary key
#  content    :text(65535)
#  done       :boolean
#  priority   :integer
#  title      :string(255)
#  created_at :datetime         not null
#  updated_at :datetime         not null
#  user_id    :bigint
#
# Indexes
#
#  index_tasks_on_user_id                 (user_id)
#  index_tasks_on_user_id_and_created_at  (user_id,created_at)
#
# Foreign Keys
#
#  fk_rails_...  (user_id => users.id)
#
class Task < ApplicationRecord
  belongs_to :user
end

routes.rbに以下の記述を追加します。

resources :tasks do
  collection do
    delete 'destroy_all'
  end
end

次にtasksコントローラーにdestroy_allアクションと

correct_user_destroy_allを定義します。

class TasksController < ApplicationController
 before_action :correct_user_destroy_all, only: :destroy_all
# 一括削除
def destroy_all
  @tasks.destroy_all
  flash[:danger] = "全て削除しました!"
  #↓ここは自由でいいです
  redirect_to request.referrer || root_url
end

private

#現在のユーザーが削除対象のtasksを保有しているかどうかを確認します。
  def correct_user_destroy_all
    @tasks = current_user.tasks
    redirect_to root_url if @tasks.nil?
  end
end

全て削除するボタンをビューに作成します。tasks/show.html.erbに以下の記述をします。

<%= button_to "全て削除", destroy_all_tasks_path, method: :delete %>
#フォントオーサムを使う場合
 <%= link_to(content_tag(:i, '', class: "fas fa-bomb fa-3x ", style: "color: rgb(80,80,80);"), destroy_all_tasks_path,
method: :delete, data: { confirm: "全て削除します。本当に削除しますか?" }) %>

destroy_allメソッドはモデルを介して削除を実行します。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です