How can we limit a user to 1 like per comment?
comments_controller.rb
def like
@comment = Comment.find(params[:id])
@comment.increment!(:likes)
@comment.create_activity :like
flash[:success] = 'Thanks for liking!'
redirect_to(:back)
end
_comments.html.erb
<% @comments.each do |comment| %>
<%= User.find(comment.user_id).name %>
<%= simple_format comment.content %>
<%= pluralize(comment.likes, 'like') %>
<%= link_to content_tag(:span, '', class: 'glyphicon glyphicon-thumbs-up') +
' Like it', like_comment_path(:id => comment.id), method: :post %>
<% end %>
valuation.rb
class Valuation < ActiveRecord::Base
belongs_to :user
has_many :comments, as: :commentable
include PublicActivity::Model
tracked owner: ->(controller, model) { controller && controller.current_user }
end
routes.rb
resources :valuations do
resources :comments
member do
post :like
end
end
I followed along this tutorial: http://www.sitepoint.com/activity-feeds-rails/ to implement the public_activity
gem and the like button.
Thank you for your time and expertise!
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 index
@comments = @commentable.comments
end
def new
@comment = @commentable.comments.new
end
def create
@comment = @commentable.comments.new(comment_params)
if @comment.save
@comment.create_activity :create, owner: current_user
redirect_to @commentable, notice: "comment created."
else
render :new
end
end
def edit
@comment = current_user.comments.find(params[:id])
end
def update
@comment = current_user.comments.find(params[:id])
if @comment.update_attributes(comment_params)
redirect_to @commentable, notice: "Comment was updated."
else
render :edit
end
end
def destroy
@comment = current_user.comments.find(params[:id])
@comment.destroy
@comment.create_activity :destroy, owner: current_user
redirect_to @commentable, notice: "comment destroyed."
end
def like
@comment = Comment.find(params[:id])
@comment.increment!(:likes)
@comment.create_activity :like
flash[:success] = 'Thanks for liking!'
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)
end
end
comment.rb
class Comment < ActiveRecord::Base
include PublicActivity::Common
# tracked except: :update, owner: ->(controller, model) { controller && controller.current_user }
belongs_to :commentable, polymorphic: true
belongs_to :user
end
I think you could create additional model:
class CommentLike
belongs_to :comment
belongs_to :user
validates :user, uniqueness: { scope: :comment}
end
class User
has_many :comment_likes
end
class Comment
has_many :comment_likes
end
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
It'll solves you problem. If storing likes_count in comment is neccessary, you could use Rails' counter_cache.