Rails中的控制器不“关心”请求的执行方式

时间:2014-08-05 10:59:13

标签: ruby-on-rails

我正在阅读一篇关于Rails控制器的文章,你能帮我理解下面这句话的含义: “最好的控制器是Dilbert-esque:它在不知道(或关心)如何完成的情况下发出命令。”

在您看来,这是真的吗?

例如,如果我正在访问与主题控制器关联的索引页面,我将严格定义subject_controller.rb中的索引方法,因此我对文章中的含义感到困惑,因为我会以为相反。

请指点什么? 谢谢,对不起,如果这太可解释了。这是原始文章:http://betterexplained.com/articles/intermediate-rails-understanding-models-views-and-controllers/

2 个答案:

答案 0 :(得分:2)

本文讨论的是MVC架构。从这样的文章中拿走的重要之处在于Rails最好用Fat Models和Thin Controller编写。这意味着您希望在模型中拥有大量的方法/函数,并希望从控制器中调用函数。索引是一个不好的例子,因为通常你不会在那里进行很多事情。

您的索引控制器通常看起来像这样

def index
  @subjects = Subject.all
end

如果您想要显示您的主题的范围顺序,您可以在模型中使用块执行此操作,如下所示:

default_scope { order("id DESC") }

一个不那么做作的例子可能看起来像这样:例如,假设您有一个接受输入的应用程序,接受该输入并根据用户输入的内容计算多个计数器。您的控制器可能名为subject_tally,如下所示:

def subject_tally
  @subject = Subject.find(params[:id])
  @subject.winnings += 1
  @subject.total_matches += 1
  @subject.win_percentage = @subject.winnings.to_f/@subject.total_matches
  redirect_to subjects_path
end

这是错误的。这是一个非常胖的控制器,很容易移动到应该

的模型。

如果写得恰当,它看起来像这样:

subjects_controller.rb :(控制器)

def subject_tally
  @subject = Subject.find(params[:id])
  @subject.subject_tally
  redirect_to subjects_path
end

subject.rb :(模特)

def subject_tally
  self.winnings += 1
  self.total_matches += 1
  self.win_percentage =winnings.to_f/total_matches
end

正如您所看到的,您只能从控制器拨打一个电话,而且它并不关心"在后端实际发生了什么。它确实在那里传递一个值(在这种情况下,是相关主题的ID)并引导你到另一个页面,在这种情况下,索引。

此外,如果您注意到,您不需要在模型的subject_tally函数中随处添加那个讨厌的@subject ......您只需使用它就可以引用对象的属性self.winnings您要在其中分配属性的地方。 Ruby足够聪明,可以知道该方法适用的当前主题(因为你从控制器调用了一个主题上的那个功能),事实上,如果你只是“{1}”,你甚至不需要self.检索属性而不是分配属性...这就是为什么我们在self或最后一行winnings.to_f之前不需要total_matches

非常方便,代码少,时间少,可以。

答案 1 :(得分:1)

  

最好的控制器是Dilbert-esque:它在不知情的情况下发出命令   (或关心)它是如何完成的。

意味着你应该在控制器中放置更少的逻辑, 控制器应该只知道要调用的内容以获得所需内容,并且不知道如何执行某项操作。

在rails开发者的“Sandy Metz规则”(http://robots.thoughtbot.com/sandi-metz-rules-for-developers)中,她说:

  

控制器只能实例化一个对象。因此,视图只能   知道一个实例变量,视图应该只发送消息   到那个对象

只有一个对象看起来有点极端,但会想到你应该在控制器中放置多少业务逻辑(没有逻辑)。