🦁

通報機能

2024/01/29に公開

はじめに

前にやってまとめきれていなかった通報についてまとめたいと思います。

イメージ

通報する側とされる側、実装のイメージはフォローフォロワーと同じ感じです。

  • reportテーブル
t.integer :reporter_id
t.integer :reported_id
t.text :reason, null: false
t.boolean :checked, default: false

reporter_id :通報したユーザー
reported_id :通報されたユーザー
reason :通報理由(内容)
checked:管理者がのフラグ(デフォルト値:false)

  • userテーブル
t.integer "user_status", default: 0
  • enum
class User < ApplicationRecord
  enum status: { available: 0, suspended: 1 }
end
  • ja.yml
ja:
    datetime:
      distance_in_words:
        x_days: "%{count}日"

#ここから!
    enums:
      user:
        user_status:
          available: "利用可能"
          suspended: "利用停止中"

アソシエーション

user.rb
has_many :reporter, class_name: "Report", foreign_key: "reporter_id", dependent: :destroy
has_many :reported, class_name: "Report", foreign_key: "reported_id", dependent: :destroy
belongs_to :reporter, class_name: "User"
belongs_to :reported, class_name: "User"

# reporter_idがuser_idである通報の件数を返すクラスメソッド(ここを追記)
  def self.reported_count(user_id)
    where(reported_id: user_id).count
  end

ルーティング

resources :users, only: [:index, :show, :edit, :update] do
        post "profile/:user_id/report" => "reports#create", as: "profile_report"
        get "profile/:user_id/report/new" => "reports#new", as: "profile_reports_new"
      end

namespace :admin do
    get 'reports/index'
    get 'reports/show'
  end

コントローラ

public /reports_controller
class Public::ReportsController < ApplicationController
  def new
    @report = Report.new
    @user = User.find(params[:user_id])
  end

  def create
    @user = User.find(params[:user_id])
    @report = Report.new(report_params)
    @report.reporter_id = current_user.id
    @report.reported_id = @user.id

    if @report.save
      redirect_to user_path(@user)
    else
      render "new"
    end
  end

  private

  def report_params
    params.require(:report).permit(:reason)
  end

end

@report.reporter_id = current_user.id
通報者(reporter_id)に今のユーザー

@report.reported_id = @user.id
通報される人(reported_id)に定義した@user.idを代入

admin/reports_controller
class Admin::ReportsController < ApplicationController
 def index
   @reports = Report.all
 end

 def show
   @report = Report.find(params[:id])
 end

 def update
   @report = Report.find(params[:id])
   if @report.update(report_params)
     redirect_to admin_reports_path
   end
 end

 private

 def report_params
   params.require(:report).permit(:checked)
 end

end

viewの作成

ユーザー

  • 通報ボタン
<% if @user != current_user %>
 <% if current_user.reporter.exists?(reported_id: @user.id) %>
  <%= button_tag "通報済み", class: "btn btn-secondary", disabled: true %>
  <% else %>
   <%= link_to "ユーザーを通報", user_profile_reports_new_path(@user), class: "btn btn-danger" %>
  <% end %>
<% end %>

自分以外のユーザーの場合かつ二度目は通報しないように設定。

report/new.html.erb
<div class="container">
  <div class="row justify-content-center">
    <div class="col-md-6">
      <h3 class="text-center">通報</h3>
      <p class="text-center">通報理由を以下にご記入ください。</p>
      <%= form_with model:[@user, @report],url: user_profile_report_path(@user), class: "my-4" do |f| %>
        <div class="form-group d-flex justify-content-center">
          <%= f.text_area :reason, rows:'3', class:"form-control" %>
        </div>
        <div class="form-group d-flex justify-content-center">
          <%= f.submit "通報する", class: "btn btn-danger" %>
        </div>
      <% end %>
    </div>
  </div>
</div>

管理者

  • view
admin/report/index.html.erb
<h2 class="heading heading-1">通報一覧</h2>
<div class="card">
  <div class="card-body">
    ※番号から通報詳細へ飛びます。
    <div class="table-responsive">
      <table class="table table-hover">
        <thead>
          <tr>
            <th>通報ID</th>
            <th>通報日</th>
            <th>会員名</th>
            <th>通報者</th>
            <th>通報された回数</th>
            <th>管理者check</th>
          </tr>
        </thead>
        <tbody>
          <% @reports.each do |report| %>
            <tr>
              <td><%= link_to report.id, admin_report_path(report) %></td>
              <td><%= report.created_at %></td>
              <td><%= report.reported.name %></td>
              <td><%= report.reporter.name %></td>
              <td><%= Report.where(reported_id: report.reported_id).count %></td>
              <td>
                <% if report.checked %>
                  <span class="badge badge-success">確認済み</span>
                <% else %>
                  <span class="badge badge-danger">未確認</span>
                <% end %>
              </td>
            </tr>
          <% end %>
        </tbody>
      </table>
    </div>
  </div>
</div>
admin/report/shoe.index.htnl.erb
<h2 class="heading heading-1">通報詳細</h2>
<div class="card mx-auto mt-5" style="width: 500px;">
  <div class="card-body">
    <div class="row">
      <div class="col-6"><strong>通報ID</strong></div>
      <div class="col-6"><%= link_to @report.id %></div>
    </div>
    <div class="row">
      <div class="col-6"><strong>会員名</strong></div>
      <div class="col-6"><%= link_to @report.reported.name, admin_user_path(@report.reported_id) %></div>
    </div>
    <div class="row">
      <div class="col-6"><strong>理由</strong></div>
      <div class="col-6"><%= @report.reason %></div>
    </div>
    <div class="row">
      <div class="col-6"><strong>通報者</strong></div>
      <div class="col-6"><%= @report.reporter.name %></div>
    </div>
    <div class="row">
      <div class="col-6"><strong>対応ステータス</strong></div>
      <div class="col-6">
        <%= form_with model:@report, url:admin_report_path(@report), method: :patch, local: true do |f| %>
          <div class="form-group text-center">
            <%= f.select :checked, { "未確認": false, "確認済み": true }, {}, class: "form-control" %>
          </div>
          <%= f.button '更新', class: "contact-edit-user-button" %>
        <% end %>
      </div>
    </div>
  </div>
  <div class="text-center">
    <%= link_to "通報一覧へ",admin_reports_path %>
  </div>
</div>

最後に

以上が通報機能の概要になります。
時間があればコメントのところにもeunmを用いて実装していきたいと思います。

Discussion