简体   繁体   English

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

[英]Rails 3 - How to refactor this controller code?

Is there a way to DRY and load objects in a cleaner way (without using before_filter). 有没有一种方法可以以更清洁的方式进行DRY和加载对象(不使用before_filter)。

Indeed I need @answer and @question in 2 other methods than "show". 实际上,除了“显示”外,我还需要其他2种方法来使用@answer和@question。

Controller : 控制器:

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

Thanks in advance 提前致谢

You could just define a method that fetches these for you if so required: 如果需要,您可以定义一个为您获取这些内容的方法:

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

This would roll this up into a simple method call in your various controller methods: 这会将其汇总为各种控制器方法中的简单方法调用:

def show
  fetch_question_and_answer(params)
  respond_with @question
end

It can be a little sneaky to go and assign instance variables in methods like this, as that does end up being a little magical in the bad sense, so be careful to label your method clearly to avoid confusion. 在这样的方法中分配实例变量可能有点费力,因为从不好的意义上来说,这的确有些不可思议 ,因此请小心标记您的方法,以免造成混淆。 The alternative is to simply return these and assign them on a case-by-case basis. 另一种选择是简单地返回这些,并根据情况进行分配。

I'm not sure why you're opposed to a before_filter method, though, as that's what those are expected to set instance variables so the same rules do not apply. 不过,我不确定为什么要反对before_filter方法,因为这正是设置实例变量的原因,因此不会应用相同的规则。

Similar to above, you can have helper methods that you can use like an instance variable: 与上面类似,您可以拥有可以像实例变量一样使用的辅助方法:

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

Since they're helper_methods, you can use them in your views too! 由于它们是helper_methods,因此您也可以在视图中使用它们!

The way you do it is good enough, except from @question.answers.page(params[:page]) that does not follow the law of Demeter and can be written in a better manner. 除了@ question.answers.page(params [:page])并不遵循Demeter的定律并且可以用更好的方式编写之外,您的操作方式已经足够好。

Instead, you can create a delegate for answers.page so that you can invoke : 相反,您可以为Answers.page创建一个委托,以便可以调用:

@question.answers_page(params[:page])

If you're interested in better design(seems like you are), remember that 2 dots in a Rails statement have a higher probability of being able to be written in a better, more encapsulating manner. 如果您对更好的设计感兴趣(看起来像您一样),请记住,Rails语句中的2个点更有可能以更好,更封装的方式编写。

If you find yourself creating new Answer and fetching params all the time, you can keep it DRYer using tadman's proposed method. 如果您发现自己一直在创建新的Answer和获取参数,则可以使用tadman提出的方法将其保持为DRYer。 And, you should consider pushing that method into a module. 并且,您应该考虑将该方法推入模块中。 However, think it through, to see if you really need to do that for DRYer code. 但是,请仔细考虑一下,看看是否真的需要对DRYer代码执行此操作。 Generally speaking, new instances and simplest finders by id tend to be used through controllers. 一般而言,新实例和ID最简单的查找器倾向于通过控制器使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM