👔

報告機能の実装

2023/09/29に公開

この記事で分かること

  • ユーザーの投稿内容を管理者に不適切な発言として報告できる

前提条件

  • ユーザー用のdeviseと管理者用のdeviseが実装済み
  • 完成イメージのようなリンクを貼る箇所を確立している
  • アソシエーション済み (記事では割愛)

完成イメージ

ユーザー側

管理者側

ER図

テーブル

実装手順

  1. reportsモデル・コントローラの作成
  2. routeingの設定
  3. 既存のページにリンク先を設定
  4. public/reports/showページ作成
  5. public/reports/completeページの作成
  6. admin/reports/indexの作成

実装方法

実装手順に沿って紹介します。

reportsモデル・コントローラの作成

以下の記述でモデルとコントローラを準備しました。

$ rails g model Report user_id:integer  item_id:integer report:text
$ rails g controller reports show

routeingの設定

私は以下の記述で実装しました。

config/routes
  scope module: :public do
    root to: "homes#top"
    get "/about" => "homes#about"
    get "search" => "searches#search"
    resources :items, only: [:new, :index, :show, :create, :destroy, :create] do
+    resource :reports, only: [:new, :create]
+    get :complete, on: :member
    end
    resources :users, only: [:show, :edit, :update] do
  end
    namespace :admin do
    root to: "homes#top"
    get "search" => "searches#search"
+  resources :reports, only: [:index]
   resources :users, only: [:show, :edit, :update]
  end

controllerを作成

public/reports_controller
class Public::ReportsController < ApplicationController
   before_action :authenticate_user!
 def new
   @report = Report.new
   @item = Item.find(params[:item_id])
 end
  def create
    item = Item.find(params[:item_id])
    report = current_user.reports.new(report_params)
    report.item_id = item.id
    if report.save
      item.update(status: 0)
      flash[:notice] = "管理者に報告しました"
      redirect_to complete_item_path(item)
    else
      @report = Report.new
      @item = Item.find(params[:item_id])
      flash[:alert] = "正しい内容を入力してください"
      render "new"
    end
  end
  private

  def report_params
    params.require(:report).permit(:report)
  end
end
admin/reports_controller
class Admin::ReportsController < ApplicationController
  before_action :authenticate_admin!
  def index
    @reports = Report.order("created_at DESC").page(params[:page])
  end
end

viewを作成

public/items/show
 <div class='container py-5 px-sm-0'>
  <div class='row'>
    <div class='col-md-3'>
      <%= render 'public/users/info', user: @user %>
      <div class= "row d-none d-md-block">
       <%= render 'form', item: @new_item %>
      </div>
      <%= render 'public/genres/genre_search', genres: @genres %>
    </div>
    <div class='col-md-8 offset-md-1 mt-3'>
      <h4><%= @user.name %>さんの投稿</h4>
      <div class="col-12 table-responsive-sm">
        <!-- テーブル略 -->
     </div>
      <div class="row justify-content-around text-center align-middle">
+     <div class="col-lg-5 col-md-7 col-sm-7 col-8 mb-lg-5 my-sm-3 my-3 background"><strong><%= link_to "不適切な投稿として報告する" ,new_item_reports_path(@item), class: "text-dark" %></strong></div>
      <div class="col-lg-5 col-md-7 col-sm-7 col-8 mb-lg-5 my-sm-3 mb-4 background"><span>投稿日 </span><%= @item.created_at.strftime('%Y/%m/%d') %></div>
     </div>
    <!-- 以下略 -->  
public/reports/new
<div class= "container py-5 px-sm-0">
  <div class= "row">
    <div class='col-md-8 col-12 offset-md-2'>
      <h4>投稿内容</h4>
      <div class="col-12 table-responsive-sm">
        <table class="table text-nowrap table-bordered">
        <!-- テーブル略 -->
       </table>
     </div>
    </div>
  </div>
  <div class= "row">
    <div class= "col-6 offset-3 mt-5">
      <h4>管理者に報告する</h4>
      <%= form_with model: [@item, @report] do |f| %>
        <%= f.text_area :report, class: 'form-control', rows: '6', placeholder: "報告内容を記載" %><br>
        <%= f.submit "報告する", class: "btn btn-outline-success" %>
      <% end %>
    </div>
  </div>
</div>
public/items/complate
<div class="container">
  <div class="row justify-content-center">
    <div class="col-12 mb-5"></div>
      <h4 class="my-5 text-center align-center">ご報告ありがとうございました!</h4>
    <div class="col-12 mb-5"></div>
  </div>
  <div class="row justify-content-center">
    <div class="col-12 mb-5"></div>
      <div class="my-5 text-center align-center"><%= link_to "マイページに戻る" ,user_path(current_user), class: "btn btn-success" %></div>
    <div class="col-12 mb-5"></div>
  </div>
</div>
admin/reports/index
<div class= "container py-5 px-sm-0">
<% if @reports.blank? %>
 <h4 class= "col-4 offset-4 mt-5 background text-center">報告はありません</h4>
<% end %>
<% @reports.each do |report| %>
  <div class= "row">
    <div class="col-lg-8 col-12 offset-lg-2">
     <div class="col-12 table-responsive-sm">
      <table class="table text-nowrap table-bordered">
       <!-- 不適切な投稿のテーブル -->
     </table>
     </div>
    </div>
  </div>
 <div class= "row justify-content-around text-center align-middle">
   <div class="col-lg-2 col-md-5 col-sm-4 col-8 mb-lg-5 my-sm-3 my-3 background"><%= report.item.status_i18n %></div>
  <div class="col-lg-2 col-md-5 col-sm-4 col-8 mb-lg-5 my-sm-3 my-3 background"><span>投稿日 </span><%= report.item.created_at.strftime('%Y/%m/%d') %></div>
 </div>
 <div class= "row">
   <div class= "col-lg-8 col-12 offset-lg-2">
    <div class="col-12 table-responsive-sm">
      <table class="table text-nowrap table-bordered">
        <!-- 報告者のテーブル -->
      </table>
    </div>
   </div>
 </div>
 <div class= "row">
  <div class="col-md-2 col-6 offset-md-8 offset-3 mb-4 mt-lg-0 mt-3 align-middle text-center background"><span>報告日 </span><%= report.created_at.strftime('%Y/%m/%d') %></div>
 </div>
<% end %>
  <div class="row justify-content-center">
     <%= paginate @reports %>
 </div>
</div>

最後にヘッダーにリンクを貼れば完成です。

感想

報告機能はadminとpublicに分かれているので難しそうに感じました。しかし実装方法は、コメント機能などと似たような感じで実装はしやすかったです。

この記事をかいた人

https://twitter.com/tya_dwc
23/6/1にDWCに入学し、主にRailsの学習に取り組みました。卒業が近づきこれから何で学習をするか悩んだときに、技術ブログをしようと考えました。初心者ですがよろしくお願いします。

Discussion