重构ruby辅助方法

时间:2010-10-12 13:55:10

标签: ruby-on-rails ruby

我有一个帮助方法来检查对象集合是否为空?如果没有,那么它会检查每一个以确保现有的event_id不是@ current_event.id。

这是我对此的抨击:

def build_answers(question)
  if question.answers.empty?
    return question.answers.build
  else
    question.answers.each do |a|
      if a.event_id != @current_event.id
        return question.answers.build
      end
    end
  end
end

更新:如果条件通过,此辅助方法将表单设置为构建新的子对象。我已经更新了上面的例子。顺便说一句,它不需要是一行。我只想要比我上面更清洁的东西。

3 个答案:

答案 0 :(得分:1)

如果不知道你在街区内实际做了什么,很难给出最好的解决方案。

在大多数情况下,在执行过滤集合上的逻辑之前,您真正要做的就是select,而不是测试块中的逻辑。

e.g。

uncurrent_answers = questions.answers.select{|a| a.event_id != @current_event.id}
uncurrent_answers.each do |a|
  #do whatever
end

恕我直言,它有点整洁,也许更红宝石......

答案 1 :(得分:1)

好吧,我不知道你为什么要把条件放到一行,但是else块可以重写成这个:

question.answers.select {|answer| answer.event_id != @current_event.id }.each
    {|ans| #.. logic with answer here }  

答案 2 :(得分:0)

我认为你现在的方法对太多事情负责,我的想法是创建一个单独负责建立答案的分支。这将使您的代码更易读,也更容易测试。一个可行的实现看起来像:

def build_answers(question)
  AnswerBuilder.build(question.answers, @current_event)
end

class AnswerBuilder
  def initialize(answers, current_event)
    @answers = answers
    @current_event = current_event
  end

  def self.build(answers, current_event)
    new(answers, current_event).build
  end

  def build
    if answers.empty?
      answers.build
    else
      create_allowed_answers
    else
  end

  private
  attr_reader :answers, :current_event

  def create_allowed_answers
    answers.each do |a|
      if a.event_id != current_event.id
        return answers.build
      end
    end
  end
end