Rails 3 - 如何重构此控制器代码?

时间:2011-05-06 16:45:08

标签: ruby-on-rails ruby-on-rails-3 refactoring

有没有办法以更干净的方式干燥和加载对象(不使用before_filter)。

事实上,除了“show”之外,我还需要@answer和@question等2种方法。

控制器:

def show
 @answer = Answer.new pre_form
 @question = Question.find(params[:id])
 @answers = @question.answers.page(params[:page])
 respond_with @question
end

private

def pre_form     
   session[:pre_form][:answer] || session[:pre_form][:question] if session[:pre_form]
end

提前致谢

3 个答案:

答案 0 :(得分:2)

如果需要,您可以定义一个为您提取这些内容的方法:

def fetch_question_and_answer(params)
  @answer = Answer.new pre_form
  @question = Question.find(params[:id])
  @answers = @question.answers.page(params[:page])
end

这会将其转换为各种控制器方法中的简单方法调用:

def show
  fetch_question_and_answer(params)
  respond_with @question
end

在这样的方法中去分配实例变量可能有点偷偷摸摸,因为在最坏的意义上它最终会变成一个魔法,所以要小心将你的方法标记为避免混淆。另一种方法是简单地返回这些并根据具体情况分配它们。

我不确定你为什么反对before_filter方法,因为这是预期设置实例变量的原因所以相同的规则不适用。

答案 1 :(得分:1)

与上面类似,您可以使用辅助方法,就像实例变量一样:

helper_method :answer, :question, :answers

def answer
  @answer ||= Answer.new pre_form
end

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

def answers
  @answers ||= question.answers.page(params[:page])
end

既然他们是helper_methods,你也可以在你的视图中使用它们!

答案 2 :(得分:1)

你做这件事的方式已经足够了,除了@ question.answers.page(params [:page]),它不符合得墨忒耳的规律,可以用更好的方式书写。

相反,您可以为answers.page创建委托,以便您可以调用:

@question.answers_page(params[:page])

如果你对更好的设计感兴趣(看起来像你),请记住,Rails语句中的2个点更有可能以更好,更封装的方式编写。

如果您发现自己一直在创建新的答案和获取参数,您可以使用tadman提出的方法保持DRYer。而且,您应该考虑将该方法推入模块中。但是,请仔细考虑,看看你是否真的需要为DRYer代码做到这一点。一般来说,id的新实例和最简单的查找器倾向于通过控制器使用。