我正在使用多态关联进行评论。我想向所有发表评论的用户发送通知。
comment.rb
class Comment < ApplicationRecord
belongs_to :user
belongs_to :commentable, polymorphic: true
has_many :comments, as: :commentable
validates :comment, presence: true
after_create :notifications
def notifications
#Create Notification
users = ????
(users-[@current_user]).each do |user|
Resque.enqueue(NotifyJob, Notification.create(
recipient: user,
actor: @current_user,
action: "posted",
notifiable: @comment))
end
end
end
user.rb
class User < ApplicationRecord
has_many :posts, dependent: :destroy
has_many :comments, as: :commentable, dependent: :destroy
has_many :notifications, foreign_key: :recipient_id, dependent: :destroy
end
post.rb
class Post < ApplicationRecord
belongs_to :user
validates :comment, presence: true
validates :user_id, presence: true
has_many :comments, as: :commentable
end
comments_controller.rb
module Api
module V1
class CommentsController < ApplicationController
skip_before_action :verify_authenticity_token
before_action :authorize_request
before_action :find_commentable
def new
@comment = Comment.new
end
def create
@comment = @commentable.comments.new(comment_params)
@comment.user = @current_user
if @comment.save
render json: @comment, status: :created
else
render json: { errors: @comment.errors.full_messages },
status: :unprocessable_entity
end
end
def show
@comment = Comment.find(params[:id])
if [email protected]?
render json: @comment, status: :ok
else
render json: {errors: @comment.errors.full_messages}, status: :unprocessable_entity
end
end
private
def comment_params
params.permit(:comment)
end
def find_commentable
@commentable = Comment.find_by_id(params[:comment_id]) if params[:comment_id]
@commentable = Post.find_by_id(params[:post_id]) if params[:post_id]
end
end
end
end
您的第一个问题是在User
模型中。您有
has_many :comments, as: :commentable, dependent: :destroy
但Comment
型号belongs_to :user
并具有user_id
,这意味着User
中应为
has_many :comments, dependent: :destroy
在这种情况下,您可以通过User.first.comments
轻松获得所有用户评论。>
第二个是回调。维亚切斯拉夫·洛文诺夫(Vyacheslav Loginov)将这种复杂的逻辑放入控制器动作中的错误做法是正确的,但回调也不是很好的做法。不知道哪个更糟。您将在每次创建注释时创建通知,即使从控制台也是如此。将在您创建commnet的每个测试设置中创建通知。不知道这是否是您真正想要的。
更好的选择是创建单独的ServiceObject来处理通知
class CommentsController < ApplicationController
def create
@comment = @commentable.comments.new(comment_params)
@comment.user = @current_user
if @comment.save
NotificationSender.new(@comment).comment_notification
render json: @comment, status: :created
else
render json: { errors: @comment.errors.full_messages },
status: :unprocessable_entity
end
end
end
class NotificationSender
def initialize(resource)
@resource = resource
end
# you can add here all other notifications as methods
def comment_notification
users = User.where(id: @resource.commentable.comments.pluck(:user_id)).
where.not(id: @resource.user_id)
users.each do |user|
Resque.enqueue(
NotifyJob,
Notification.create(
recipient: user,
actor: @resource.user,
action: "posted",
notifiable: @resource
)
)
end
end
end