From 2772cb6e0c4280b7cf7f230773fac0a0fc7aee28 Mon Sep 17 00:00:00 2001 From: Steffen van Bergerem <svbergerem@omgsrsly.net> Date: Sat, 18 Feb 2017 00:36:22 +0100 Subject: [PATCH] Refactor likes controller using like service --- app/controllers/likes_controller.rb | 49 ++--- spec/controllers/likes_controller_spec.rb | 233 ++++++++++------------ 2 files changed, 119 insertions(+), 163 deletions(-) diff --git a/app/controllers/likes_controller.rb b/app/controllers/likes_controller.rb index 8f9197c3c5..6767464f7d 100644 --- a/app/controllers/likes_controller.rb +++ b/app/controllers/likes_controller.rb @@ -11,42 +11,27 @@ class LikesController < ApplicationController :json def create - begin - @like = if target - current_user.like!(target) - end - rescue ActiveRecord::RecordNotFound, ActiveRecord::RecordInvalid => e - # do nothing - end - - if @like - respond_to do |format| - format.html { render :nothing => true, :status => 201 } - format.mobile { redirect_to post_path(@like.post_id) } - format.json { render :json => @like.as_api_response(:backbone), :status => 201 } - end - else - render text: I18n.t("likes.create.error"), status: 422 + like = like_service.create(params[:post_id]) + rescue ActiveRecord::RecordNotFound, ActiveRecord::RecordInvalid + render text: I18n.t("likes.create.error"), status: 422 + else + respond_to do |format| + format.html { render nothing: true, status: 201 } + format.mobile { redirect_to post_path(like.post_id) } + format.json { render json: like.as_api_response(:backbone), status: 201 } end end def destroy - begin - @like = Like.find_by_id_and_author_id!(params[:id], current_user.person.id) - rescue ActiveRecord::RecordNotFound + if like_service.destroy(params[:id]) + render nothing: true, status: 204 + else render text: I18n.t("likes.destroy.error"), status: 404 - return - end - - current_user.retract(@like) - respond_to do |format| - format.json { render :nothing => true, :status => 204 } end end - #I can go when the old stream goes. def index - @likes = target.likes.includes(:author => :profile) + @likes = like_service.find_for_post(params[:post_id]).includes(author: :profile) @people = @likes.map(&:author) respond_to do |format| @@ -57,13 +42,7 @@ class LikesController < ApplicationController private - def target - @target ||= if params[:post_id] - current_user.find_visible_shareable_by_id(Post, params[:post_id]) || raise(ActiveRecord::RecordNotFound.new) - else - Comment.find(params[:comment_id]).tap do |comment| - raise(ActiveRecord::RecordNotFound.new) unless current_user.find_visible_shareable_by_id(Post, comment.commentable_id) - end - end + def like_service + @like_service ||= LikeService.new(current_user) end end diff --git a/spec/controllers/likes_controller_spec.rb b/spec/controllers/likes_controller_spec.rb index 928b1f64ca..f26306776e 100644 --- a/spec/controllers/likes_controller_spec.rb +++ b/spec/controllers/likes_controller_spec.rb @@ -1,8 +1,8 @@ - # Copyright (c) 2010-2011, Diaspora Inc. This file is +# Copyright (c) 2010-2011, Diaspora Inc. This file is # licensed under the Affero General Public License version 3 or later. See # the COPYRIGHT file. -describe LikesController, :type => :controller do +describe LikesController, type: :controller do before do @alices_aspect = alice.aspects.where(:name => "generic").first @bobs_aspect = bob.aspects.where(:name => "generic").first @@ -10,137 +10,114 @@ describe LikesController, :type => :controller do sign_in(alice, scope: :user) end - [Comment, Post].each do |class_const| - context class_const.to_s do - let(:id_field){ - "#{class_const.to_s.underscore}_id" - } - - describe '#create' do - let(:like_hash) { - {:positive => 1, - id_field => "#{@target.id}"} - } - let(:dislike_hash) { - {:positive => 0, - id_field => "#{@target.id}"} - } - - context "on my own post" do - it 'succeeds' do - @target = alice.post :status_message, :text => "AWESOME", :to => @alices_aspect.id - @target = alice.comment!(@target, "hey") if class_const == Comment - post :create, like_hash.merge(:format => :json) - expect(response.code).to eq('201') - end - end - - context "on a post from a contact" do - before do - @target = bob.post(:status_message, :text => "AWESOME", :to => @bobs_aspect.id) - @target = bob.comment!(@target, "hey") if class_const == Comment - end - - it 'likes' do - post :create, like_hash - expect(response.code).to eq('201') - end - - it 'dislikes' do - post :create, dislike_hash - expect(response.code).to eq('201') - end - - it "doesn't post multiple times" do - alice.like!(@target) - post :create, dislike_hash - expect(response.code).to eq('422') - end - end - - context "on a post from a stranger" do - before do - @target = eve.post :status_message, :text => "AWESOME", :to => eve.aspects.first.id - @target = eve.comment!(@target, "hey") if class_const == Comment - end - - it "doesn't post" do - expect(alice).not_to receive(:like!) - post :create, like_hash - expect(response.code).to eq('422') - end - end - - context "when an the exception is raised" do - before do - @target = alice.post :status_message, :text => "AWESOME", :to => @alices_aspect.id - @target = alice.comment!(@target, "hey") if class_const == Comment - end - - it "should be catched when it means that the target is not found" do - params = like_hash.merge(format: :json, id_field => -1) - post :create, params - expect(response.code).to eq('422') - end - - it "should not be catched when it is unexpected" do - @target = alice.post :status_message, :text => "AWESOME", :to => @alices_aspect.id - @target = alice.comment!(@target, "hey") if class_const == Comment - allow(alice).to receive(:like!).and_raise("something") - allow(@controller).to receive(:current_user).and_return(alice) - expect { post :create, like_hash.merge(:format => :json) }.to raise_error("something") - end - end + describe "#create" do + let(:like_hash) { + {post_id: @target.id} + } + + context "on my own post" do + it "succeeds" do + @target = alice.post :status_message, text: "AWESOME", to: @alices_aspect.id + post :create, like_hash.merge(format: :json) + expect(response.code).to eq("201") end + end + + context "on a post from a contact" do + before do + @target = bob.post(:status_message, text: "AWESOME", to: @bobs_aspect.id) + end + + it "likes" do + post :create, like_hash + expect(response.code).to eq("201") + end + + it "doesn't post multiple times" do + alice.like!(@target) + post :create, like_hash + expect(response.code).to eq("422") + end + end - describe '#index' do - before do - @message = alice.post(:status_message, :text => "hey", :to => @alices_aspect.id) - @message = alice.comment!(@message, "hey") if class_const == Comment - end - - it 'returns a 404 for a post not visible to the user' do - sign_in eve - expect{get :index, id_field => @message.id}.to raise_error(ActiveRecord::RecordNotFound) - end - - it 'returns an array of likes for a post' do - like = bob.like!(@message) - get :index, id_field => @message.id - expect(assigns[:likes].map(&:id)).to eq(@message.likes.map(&:id)) - end - - it 'returns an empty array for a post with no likes' do - get :index, id_field => @message.id - expect(assigns[:likes]).to eq([]) - end + context "on a post from a stranger" do + before do + @target = eve.post :status_message, text: "AWESOME", to: eve.aspects.first.id end - describe '#destroy' do - before do - @message = bob.post(:status_message, :text => "hey", :to => @alices_aspect.id) - @message = bob.comment!(@message, "hey") if class_const == Comment - @like = alice.like!(@message) - end - - it 'lets a user destroy their like' do - current_user = controller.send(:current_user) - expect(current_user).to receive(:retract).with(@like) - - delete :destroy, :format => :json, id_field => @like.target_id, :id => @like.id - expect(response.status).to eq(204) - end - - it 'does not let a user destroy other likes' do - like2 = eve.like!(@message) - like_count = Like.count - - delete :destroy, :format => :json, id_field => like2.target_id, :id => like2.id - expect(response.status).to eq(404) - expect(response.body).to eq(I18n.t("likes.destroy.error")) - expect(Like.count).to eq(like_count) - end + it "doesn't post" do + expect(alice).not_to receive(:like!) + post :create, like_hash + expect(response.code).to eq("422") end end + + context "when an the exception is raised" do + before do + @target = alice.post :status_message, text: "AWESOME", to: @alices_aspect.id + end + + it "should be catched when it means that the target is not found" do + params = like_hash.merge(format: :json, post_id: -1) + post :create, params + expect(response.code).to eq("422") + end + + it "should not be catched when it is unexpected" do + @target = alice.post :status_message, text: "AWESOME", to: @alices_aspect.id + allow(alice).to receive(:like!).and_raise("something") + allow(@controller).to receive(:current_user).and_return(alice) + expect { post :create, like_hash.merge(format: :json) }.to raise_error("something") + end + end + end + + describe "#index" do + before do + @message = alice.post(:status_message, text: "hey", to: @alices_aspect.id) + end + + it "returns a 404 for a post not visible to the user" do + sign_in eve + expect { + get :index, post_id: @message.id + }.to raise_error(ActiveRecord::RecordNotFound) + end + + it "returns an array of likes for a post" do + bob.like!(@message) + get :index, post_id: @message.id + expect(assigns[:likes].map(&:id)).to eq(@message.likes.map(&:id)) + end + + it "returns an empty array for a post with no likes" do + get :index, post_id: @message.id + expect(assigns[:likes]).to eq([]) + end + end + + describe "#destroy" do + before do + @message = bob.post(:status_message, text: "hey", to: @alices_aspect.id) + @like = alice.like!(@message) + end + + it "lets a user destroy their like" do + current_user = controller.send(:current_user) + expect(current_user).to receive(:retract).with(@like) + + delete :destroy, format: :json, post_id: @message.id, id: @like.id + expect(response.status).to eq(204) + end + + it "does not let a user destroy other likes" do + like2 = eve.like!(@message) + like_count = Like.count + + delete :destroy, format: :json, post_id: @message.id, id: like2.id + expect(response.status).to eq(404) + expect(response.body).to eq(I18n.t("likes.destroy.error")) + expect(Like.count).to eq(like_count) + end end end -- GitLab