DRY投票方式

DRY voting methods

我收到一个提示,要求使用 'redirect_to' 和 'update_vote!' 方法仅在两行中编写我的 up_vote 和 down_vote 方法,如下所示。实施 redirect_to 很容易,但我不太确定如何使用现有的 'update_vote!' 方法简洁地编写我的 up/down_vote 方法。任何帮助表示赞赏。

 class VotesController < ApplicationController
      before_action :load_post_and_vote

      def up_vote

        if @vote
          @vote.update_attribute(:value, 1)
        else
          @vote = current_user.votes.create(value: 1, post: @post)
        end

        # http://apidoc.com/rails/ActionController/Base/redirect_to
        redirect_to :back
      end

      def down_vote

        if @vote
          @vote.update_attribute(:value, -1)
        else
          @vote = current_user.votes.create(value: -1, post: @post)
        end

        # http://apidoc.com/rails/ActionController/Base/redirect_to
        redirect_to :back
      end

      private

      def load_post_and_vote
        @post = Post.find(params[:post_id])

        @vote = @post.votes.where(user_id: current_user.id).first
      end

      def update_vote!(new_value)
        if @vote
          authorize @vote, :update?
          @vote.update_attribute(:value, new_value)
        else
          @vote = current_user.votes.build(value: new_value, post: @post)
          authorize @vote, :create
          @vote.save
        end
      end
    end

您应该调用 update_vote! 方法。怎么样:

def up_vote        
  update_vote!(1)
  # http://apidoc.com/rails/ActionController/Base/redirect_to
  redirect_to :back
end

def down_vote
    update_vote!(-1)
    # http://apidoc.com/rails/ActionController/Base/redirect_to
    redirect_to :back
end

您的方法也可以重写为:

def update_vote!(new_value)
  Vote.find_or_create_by post: @post do |v|
    authorize v, :update?
    v.user_id = current_user.id
    v.value = new_value
    v.save!
  end
end

阅读find_or_create_by

看来答案很简单=]

def up_vote
  update_vote(1)
  redirect_to :back
end

def down_vote
  update_vote(-1)
  redirect_to :back
end