Ruby on rails 我将如何重构我的控制器';什么是自定义方法?

Ruby on rails 我将如何重构我的控制器';什么是自定义方法?,ruby-on-rails,ruby-on-rails-4,Ruby On Rails,Ruby On Rails 4,我正在构建一个类似StackOverflow的克隆,以供研究之用。用户可以为某人的问题投票,从而提高或降低分数。我的方法工作得很好,但是重复和控制器逻辑的数量困扰着我 用户拥有多张选票 这个问题有很多票 投票属于问题/用户 路线: concern :voteable do post 'votes/voteup', to: 'votings#voteup', as: :voteup post 'votes/votedown', to: 'votings#votedown', a

我正在构建一个类似StackOverflow的克隆,以供研究之用。用户可以为某人的问题投票,从而提高或降低分数。我的方法工作得很好,但是重复和控制器逻辑的数量困扰着我

  • 用户拥有多张选票
  • 这个问题有很多票
  • 投票属于问题/用户
路线:

concern :voteable do
  post 'votes/voteup',   to: 'votings#voteup',   as: :voteup
  post 'votes/votedown', to: 'votings#votedown', as: :votedown
end

resources :questions, concerns: [:commentable, :favoriteable, :voteable] do
  ...
end
投票控制员

class VotingsController < ApplicationController
  def voteup
    @question = Question.find(params[:question_id])

    unless @question.user == current_user # checks if the user is the author
      if current_user.voted?(@question.id) #checks if user already voted
        @vote = current_user.votes.find_by(question_id: @question)
        @vote.update_attributes(score: 1)
      else
        @vote = Vote.create(user: current_user, question: @question, score: 1)
      end
    end

    redirect_to :back
  end

  def votedown
    @question = Question.find(params[:question_id])

    unless @question.user == current_user
      if current_user.voted?(@question.id) 
        @vote = current_user.votes.find_by(question_id: @question)
        @vote.update_attributes(score: -1)
      else
        @vote = Vote.create(user: current_user, question: @question, score: -1)
      end
    end

    redirect_to :back
  end
end
我想消除这两种方法中的重复,但如何做到?
我是否应该创建一个类似投票的方法和一个使用指定参数(向上/向下)指向它的路线,然后根据if/else分配分数?听起来很肮脏,但这是我唯一想到的。我相信一定有一个漂亮的Rails解决方案

用户类可以持有一个名为
vote\u for(问题、分数)
的方法,其定义如下:

# class User
def vote_for(question, score)
  vote = self.votes.where(question_id: question.id).first || Vote.new(user: self, question: question)
  vote.score = score
  vote.save
end


class VotingsController < ApplicationController
  before_filter :set_question, only: %w(voteup votedown)

  def voteup
    current_user.vote_for(@question, 1)
  end

  def votedown
    current_user.vote_for(@question, -1)
  end

  protected
  def set_question
    @question = Question.find(params[:id])
  end

这将返回
TRUE
FALSE
,而不是从数据库检索到的完整对象,然后转换为Ruby对象。

谢谢。我走了你的路,经过一些重构,我的代码现在看起来好多了
# class User
def vote_for(question, score)
  vote = self.votes.where(question_id: question.id).first || Vote.new(user: self, question: question)
  vote.score = score
  vote.save
end


class VotingsController < ApplicationController
  before_filter :set_question, only: %w(voteup votedown)

  def voteup
    current_user.vote_for(@question, 1)
  end

  def votedown
    current_user.vote_for(@question, -1)
  end

  protected
  def set_question
    @question = Question.find(params[:id])
  end
def voted?(question)
  self.votes.exists?(question_id: question)
end