Rails模型,视图,控制器和助手:什么去哪里?

在Ruby on Rails开发(或一般的MVC)中,我应该遵循哪些快速规则来放置逻辑。

请回答是肯定的 – 用这个把这个放在这里 ,而不要放在那里

MVC

Controller(控制器) :把代码放在这里,用来确定用户想要什么,并决定要给他们什么,确定他们是否已经login,是否应该看到某些数据等等。最后,控制器查看请求并计算出要显示的数据(模型)以及要呈现的视图。 如果你怀疑代码是否应该放在控制器中,那么它可能不应该。 保持你的控制器瘦 。

视图 :该视图应该只包含显示数据(模型)的最小代码,不应该做大量的处理或计算,它应该显示由模型计算(或汇总)的数据,或者由控制器生成。 如果你的View真的需要做模型或控制器无法完成的处理,把代码放在Helper中。 View中的许多Ruby代码使得页面标记难以阅读。

模型 :您的模型应该是所有与您的数据相关的代码(组成您的网站的实体,例如用户,发布,帐户,朋友等)所在的地方。 如果代码需要保存,更新或汇总与您实体相关的数据,请将其放在此处。 它将在您的视图和控制器中重复使用。

要添加到pauliephonic的答案:

助手 :使创build视图更容易的function。 例如,如果您总是迭代小部件列表以显示其价格,请将其放入帮助器(以及部分实际显示)。 或者如果你有一个RJS,你不想混乱的视图,把它放进一个帮手。

MVC模式实际上只关心用户界面,没有别的。 您不应该在控制器中放置任何复杂的业务逻辑,因为它控制视图而不是逻辑。 控制器应该关心自己select正确的视图,并将更复杂的东西委托给域模型(Model)或业务层。

领域驱动devise有一个服务的概念,这是一个你坚持逻辑的地方,它需要编排一些各种types的对象,这通常意味着自然不属于Model类的逻辑。

我通常认为服务层是我的应用程序的API。 我的服务层通常与我创build的应用程序的要求非常接近,因此服务层可以简化更复杂的交互,这些更复杂的交互在我的应用程序的较低级别中find,即,您可以完成绕过服务层的相同目标但是你必须拉动更多的杠杆才能使其工作。

请注意,我不是在说Rails在这里,我正在谈论一个解决您的特定问题的一般架构风格。

这里已经有完美的解释,一个非常简单的句子作为结论,容易记住:

我们需要SMART模型,薄控制器和DUMB视图。

http://c2.com/cgi/wiki?ModelViewController

Rails的方式是有瘦的控制器和胖模型 。

把与授权/访问控制有关的东西放在控制器中。

模型都是关于你的数据的。 validation,关系,CRUD,业务逻辑

视图是关于显示您的数据。 仅显示和获取input。

控制器是关于控制什么数据从你的模型到你的视图(以及哪个视图),从你的视图到你的模型。 控制器也可以不存在模型。

我喜欢将pipe制员视为一名保安员/接待员,他将客户(请求)指引到适当的柜台,在柜台向出纳员(查看)提问。 然后,出纳员(视图)就会从经理(模特)那里得到答案,你从来没有看到过。 你要求回到保安/接待员(控制员),然后等待,直到你指示另一个出纳员(视图)告诉你经理(模型)告诉他们回答其他出纳员(查看)问题的答案。

同样,如果你想告诉出纳员(查看)什么,那么基本上会发生同样的事情,除了第二个出纳员会告诉你经理是否接受你的信息。 由于您没有被授权告知经理这些信息,保安/接待员(pipe理员)可能已经告诉您要加息。

因此,为了扩大这个比喻,在我刻板的,不切实际的世界里,出纳员(观点)是相当空洞的,常常相信你所告诉他们的任何事情,保安/接待员是最不礼貌的,但不是非常有知识,但他们知道人们应该不应该去,pipe理者是真的丑陋和卑鄙,但知道一切,可以告诉什么是真的,什么不是。

有一件事帮助正确分离是避免“从控制器通过局部variables查看”的反模式。 而不是这个:

# app/controllers/foos_controller.rb: class FoosController < ApplicationController def show @foo = Foo.find(...) end end #app/views/foos/show.html.erb: ... <%= @foo.bar %> ... 

尝试将它移动到可用作辅助方法的getter:

 # app/controllers/foos_controller.rb: class FoosController < ApplicationController helper_method :foo def show end protected def foo @foo ||= Foo.find(...) end end #app/views/foos/show.html.erb: ... <%= foo.bar %> ... 

这样可以更容易地修改放在“@foo”中的内容以及如何使用它。 它增加了控制器和视图之间的分离,而不会使它们变得更复杂。

那么,这取决于逻辑处理的内容。

通常情况下,将更多的东西推入模型是很有意义的,而控制器则很小。 这确保了可以从任何需要访问模型所代表的数据的地方轻松使用该逻辑。 意见应该包含几乎没有逻辑。 所以,一般来说,你应该努力做到让你不要重复自己。

此外,谷歌的一点点揭示了什么去哪里的几个更具体的例子。

模型:validation需求,数据关系,创build方法,更新方法,销毁方法,查找方法(注意你不应该只有这些方法的通用版本,但是如果你有很多事情要做,比如找红色的人头发的姓氏,那么你应该提取的逻辑,所以你所要做的就是调用find_redH_by_name(“smith”)或类似的东西)

查看:这应该是关于数据的格式化,而不是数据的处理。

控制器:这是数据处理的地方。 在互联网上:“控制器的目的是响应用户请求的动作,取用户设置的任何参数,处理数据,与模型交互,然后将所请求的数据以最终forms传递给视图。”

希望有所帮助。

简而言之,一般来说, 模型将拥有所有与表相关的代码,它们简单或复杂的关系(将它们视为涉及多个表的sql查询),操纵数据/variables以使用业务逻辑得出结果。

控制器将具有针对所要求工作的相关模型的代码/指针。

视图将接受用户input/交互并显示结果响应。

任何重大的偏差都会给该部分带来不必要的压力,整体应用性能可能会受到影响。

testing,testing…在模型中放置尽可能多的逻辑,然后您将能够正确地进行testing。 unit testing通过testing模型来testing数据及其形成方式,functiontesting通过testing控制器来testing路由或控制的方式,因此,除非testing数据完整性,否则不能testing数据的完整性该模型。

Ĵ