如何通过固定控制器将 "Like" 限制为 1?

How to limit "Like" to 1 by fixing controller?

我们在模型中将用户限制为每个评论 1 Like,但是我们如何在控制器中执行此操作,因为现在用户仍然可以 Like 不断点击 喜欢 按钮,直到无穷大?

class CommentsController < ApplicationController
  before_action :load_commentable
  before_action :set_comment, only: [:show, :edit, :update, :destroy, :like]
  before_action :logged_in_user, only: [:create, :destroy]


  def like
    @comment = Comment.find(params[:id])
    if current_user.comment_likes.create(comment: @comment)
        @comment.increment!(:likes)
        @comment.create_activity :like
        flash[:success] = 'Thanks for liking!'
    else
        flash[:error] = 'Two many likes'
    end  
    redirect_to(:back)
  end

private
  def set_comment
    @comment = Comment.find(params[:id])
  end

  def load_commentable
    resource, id = request.path.split('/')[1, 2]
    @commentable = resource.singularize.classify.constantize.find(id)
  end

  def comment_params
    params[:comment][:user_id] = current_user.id
    params.require(:comment).permit(:content, :commentable, :user_id, :like)
  end
end

这就是我们知道模型正在运行的方式:

在控制台中:

CommentLike.create!(user: User.first, comment: Comment.first)

User Load (0.3ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT 1 
Comment Load (0.3ms) SELECT "comments".* FROM "comments" ORDER BY "comments"."id" ASC LIMIT 1 
(0.1ms) begin transaction CommentLike Exists 
(0.2ms) SELECT 1 AS one FROM "comment_likes" WHERE 
("comment_likes"."user_id" = 1 AND "comment_likes"."comment_id" = 1) 
LIMIT 1 

(0.1ms) rollback transaction ActiveRecord::RecordInvalid: Validation failed: User has already been taken

我们从这里继续对话: 因为回答者和我无法弄清楚控制器哪里出了问题。

感谢您的专业知识!

添加对 CommentLike 的验证。

validates_uniqueness_of :user_id, :scope => :comment_id

create 总是 returns 真值 - 在这样的 if 语句中使用它没有意义。

你可以

comment_like = current_user.comment_likes.build(comment: @comment)
if comment_like.save
  ...
else
  ...
end

或者继续使用 create 但检查对象是否实际保存(persisted? 会告诉你)

另一种方法是在 CommentLike 模型上使用 after_create 挂钩来增加 Comment.likes

在您的 CommentLike 模型中

...
after_create :increment_comment

...
private
def increment_comment
  comment.increment! :likes
  comment.create_activity :like
end

您的 like 方法现在看起来像这样:

def like
  clike = current_user.comment_likes.where(comment: @comment).first
  if clike.nil?
    current_user.comment_likes.create!(comment: @comment)
    flash[:success] = 'Thanks for liking!'
  else
    flash[:error] = 'Two many likes'
  end
  redirect_to :back
end