Я пытаюсь создать модель (отчет), которая будет обрабатывать злоупотребления пользователей в моем приложении rails. Однако у меня проблема с моими полиморфными c ресурсами. Пользователи должны иметь возможность сообщать о злоупотреблениях как в моментах, так и в комментариях, но я не уверен, как реализовать это в моей форме и маршрутах (комментарии вложены в моменты моментов). Как мне это реализовать?
class Moment < ApplicationRecord
acts_as_votable
extend FriendlyId
friendly_id :name, use: :slugged
has_many :comments, as: :commentable
belongs_to :user
has_many :bookmarks, as: :bookmarkable
has_many :reports, as: :reportable
has_many :commented_users, through: :comments, source: :user
has_many :bookmarked_users, through: :bookmarks, source: :user
has_many :voted_users, through: :votes, source: :user
has_one_attached :content
acts_as_notifiable :users,
targets: ->(vote, key) {
([vote.votable.user] + vote.votable.voted_users.to_a - [vote.user]).uniq
},
notifiable_path: :vote_notifiable_path
def moment_notifiable_path
polymorphic_path(votable)
end
validates :name, presence: true
validates :content ,attached: true, content_type: ['image/png', 'image/jpg', 'image/jpeg', 'video/mp4']
def bookmarked_by?(user)
return true if bookmarks.any? {|b| b.user == user }
end
def votable_type
user = User.find_by(id: value)
end
end
class Comment < ApplicationRecord
extend FriendlyId
acts_as_votable
friendly_id :body, use: :slugged
has_many :reports, as: :reportable
belongs_to :user, dependent: :destroy
belongs_to :commentable, polymorphic: true
validates :body, presence: true
acts_as_notifiable :users,
targets: ->(comment, key) {
([comment.commentable.user] + comment.commentable.commented_users.to_a - [comment.user]).uniq
},
notifiable_path: :moment_notifiable_path
def moment_notifiable_path
polymorphic_path(commentable)
end
end
class Report < ApplicationRecord
REASONS = %w[SPAM, PORNOGRAPHY, HATE SPEECH, BULLYING]
belongs_to :user
belongs_to :reportable, polymorphic: true
validates :reason, presence: true
end
Rails.application.routes.draw do
mount RailsAdmin::Engine => '/admin', as: 'rails_admin'
root "moments#index"
notify_to :users, with_devise: :users, controller: 'users/notifications_with_devise'
notify_to :admins, with_devise: :users, controller: 'admins/notifications_with_devise'
devise_for :users, controllers: {
registrations: 'registrations',
confirmations: 'confirmations'
# match '/users/:id', to: 'registrations#show', via: 'get', as: 'user'
}
devise_scope :user do
get '/users/:id', to: 'registrations#show', as: :user
end
resources :moments do
resources :reports, module: :moments
resources :comments, module: :moments do
resources :reports, module: :comments
end
end
resources :votes
resources :bookmarks
# resources :reports
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end
reports controller.rb
class ReportsController < ApplicationController
before_action :authenticate_user!
load_and_authorize_resource
def new
@report = report.new
end
def create
reportable = @reportable
@report = @reportable.reports.build(report_params)
@report.user = current_user
respond_to do |format|
if @report.save
# @report.notify :users, key: 'report.create'
format.js
format.html { redirect_to @reportable, notice: "Your report was successfully posted."
}
else
format.js
end
end
end
def edit
@report = @reportable.reports.friendly.find(params[:id]) || @reportable.reports.find_by(params[:id])
# if @report.user == current_user or current_user.has_role? :admin
# else
# redirect_to root_path
# end
end
def destroy
@report = @reportable.reports.friendly.find(params[:id])
# if @report.user == current_user or current_user.has_role? :admin
# else
# redirect_to root_path
# end
respond_to do |format|
if @report.destroy
format.html {redirect_to @reportable, notice: "Your report was deleted"}
format.js
else
format.html { redirect_to @reportable, notice: "There was an error. Please try again."}
format.html
end
end
end
def update
respond_to do |format|
@report = @reportable.reports.friendly.find(params[:id])
if @report.update(report_params)
format.html { redirect_to @reportable, notice: 'Your report was updated.' }
format.js
else
format.html { render :edit }
format.json { render json: [@reportable, @report], status: :unprocessable_entity }
end
end
end
private
def report_params
params.require(:report).permit(:reason, :reportable_id, :reportable_type)
end
end
app/controllers/moments/reports_controller.rb
class Moments::ReportsController < ReportsController
before_action :set_reportable
private
def set_reportable
@reportable = Moment.friendly.find(params[:moment_id])
end
end