From ad02b890db76d6d7623d0c22cf52b4dea498662d Mon Sep 17 00:00:00 2001 From: Paul McKissock Date: Fri, 28 Jun 2024 15:46:23 -0400 Subject: [PATCH] Added upvote and downvote to comment controller and wrote tests for them. --- app/controllers/comments_controller.rb | 45 +++++++++++++++++--- config/routes.rb | 7 ++- spec/controllers/comments_controller_spec.rb | 34 +++++++++++++++ 3 files changed, 78 insertions(+), 8 deletions(-) diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb index 9b512d9..741d1dd 100644 --- a/app/controllers/comments_controller.rb +++ b/app/controllers/comments_controller.rb @@ -2,26 +2,57 @@ class CommentsController < ApplicationController before_action :authorized, only: [:create] def show - @comment = Comment.find(params[:id]) @reply = Comment.new + @user_votes = Vote.where(user: current_user, votable: @comments.to_a).index_by(&:votable_id) + + end + + def upvote + vote(1) + redirect_to article_comment_path(comment) + end + + def downvote + vote(-1) + redirect_to article_comment_path(comment) end def create - @article = Article.find(params[:article_id]) - @comment = @article.comments.new(comment_params) - @comment.user = current_user + @comment = article.comments.new(comment_params) + comment.user = current_user - if @comment.save - redirect_to @article + if comment.save + if comment.parent_id.present? + redirect_to article_comment_path(article, @comment.parent_id) + else + redirect_to article + end else - @comments = @article.comments.order(created_at: :desc) render "articles/show", status: :unprocessable_entity end end + private + def article + @article ||= Article.find(params[:article_id]) + end + + def comment + @comment ||= Comment.find(params[:id]) + end + def comment_params params.require(:comment).permit(:text, :parent_id) end + + def vote(value) + vote = comment.votes.find_or_initialize_by(user: current_user) + if vote.value == value + vote.update(value: 0) + else + vote.update(value: value) + end + end end diff --git a/config/routes.rb b/config/routes.rb index 77d0917..8f90595 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,7 +1,12 @@ Rails.application.routes.draw do root "articles#index" resources :articles do - resources :comments, only: [:create, :show] + resources :comments, only: [:create, :show] do + member do + post "upvote" + post "downvote" + end + end member do post "upvote" post "downvote" diff --git a/spec/controllers/comments_controller_spec.rb b/spec/controllers/comments_controller_spec.rb index e634f0e..dffdf83 100644 --- a/spec/controllers/comments_controller_spec.rb +++ b/spec/controllers/comments_controller_spec.rb @@ -3,6 +3,7 @@ RSpec.describe CommentsController, type: :controller do let(:user) { create(:user) } let(:article) { create(:article, user: user) } + let(:comment) {create(:comment, user: user, article: article)} let(:parent_comment) { create(:comment, article: article, user: user) } let(:comment_params) { {text: "This is a test comment"} } let(:reply_params) { {text: "This is a test reply", parent_id: parent_comment.id} } @@ -52,5 +53,38 @@ } expect(response.code).to eq("422") end + describe "POST #upvote" do + it "sets vote value to 1 if user has not voted" do + expect { + post :upvote, params: {article_id: article.id, id: comment.id} + }.to change { comment.votes.count }.by(1) + expect(comment.reload.votes.last.value).to eq(1) + end + + it "sets vote value to 0 if user has already upvoted" do + create(:vote, votable: comment, user: user, value: 1) + expect { + post :upvote, params: {article_id: article.id, id: comment.id} + }.not_to change { comment.votes.count } + expect(comment.reload.votes.last.value).to eq(0) + end + end + + describe "POST #downvote" do + it "sets vote value to -1 if user has not already downvoted" do + expect { + post :downvote, params: {article_id: article.id, id: comment.id}, format: :json + }.to change { comment.votes.count }.by(1) + expect(comment.reload.votes.last.value).to eq(-1) + end + + it "sets vote value to 0 if user has already downvoted" do + create(:vote, votable: comment, user: user, value: -1) + expect { + post :downvote, params: {article_id: article.id, id: comment.id} + }.not_to change { comment.votes.count } + expect(comment.reload.votes.last.value).to eq(0) + end + end end end