0

We limited the user to 1 Like per comment in the model, but how can we do this in the controller because right now the user can still Like to infinity by keeping clicking the Like button repeatedly?

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

This is how we know the models are working:

In Console:

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

We continued the conversation from over here: Limit user to 1 like? because the answerer and I couldn't figure out where the controller was going wrong.

Thank you for your expertise!

Community
  • 1
  • 1
AnthonyGalli.com
  • 2,796
  • 5
  • 31
  • 80
  • I agree with @FrederickCheung do not use `#create` also you realize you are setting `@comment` twice this is not the issue just a note. It is a lot easier to see now that only the pertinent information is shown – engineersmnky Apr 17 '15 at 17:45

3 Answers3

2

Add a validation on CommentLike.

validates_uniqueness_of :user_id, :scope => :comment_id

fylooi
  • 3,840
  • 14
  • 24
2

create always returns a truthy value - it doesn't make sense to use it in an if statement like that.

you could do

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

Or altnernatively keep using create but check whether the object was actually saved (persisted? will tell you this)

Frederick Cheung
  • 83,189
  • 8
  • 152
  • 174
2

Another approach is to use after_create hook at CommentLike model to increment Comment.likes

inside your CommentLike model

...
after_create :increment_comment

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

your like method now looks like this:

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
fudanchii
  • 192
  • 4