155

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

请给予肯定的回答——Do put this here,而不是Don't put that there

4

10 回答 10

173

MVC

控制器:将代码放在这里,用于确定用户想要什么,决定给他们什么,确定他们是否登录,他们是否应该看到某些数据等。最后,控制器查看请求并计算出要显示的数据(模型)和要渲染的视图。如果您对代码是否应该进入控制器有疑问,那么它可能不应该。保持你的控制器

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

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

于 2008-09-13T19:59:14.953 回答
37

要添加到 pauliephonic 的答案:

Helper:使创建视图更容易的功能。例如,如果您总是遍历小部件列表以显示其价格,请将其放入帮助程序(以及用于实际显示的部分)。或者,如果您不想弄乱视图,请将其放入帮助程序中。

于 2008-09-13T20:18:46.013 回答
14

MVC 模式实际上只关心 UI 而不是其他的。您不应该在控制器中放置任何复杂的业务逻辑,因为它控制视图而不是逻辑。控制器应该关注选择正确的视图并将更复杂的东西委托给领域模型(模型)或业务层。

领域驱动设计有一个服务的概念,这是一个你坚持逻辑的地方,它需要编排许多不同类型的对象,这通常意味着不自然属于模型类的逻辑。

我通常将服务层视为我的应用程序的 API。我的服务层通常与我正在创建的应用程序的要求非常接近,因此服务层充当了在我的应用程序的较低级别中发现的更复杂交互的简化,即您可以绕过服务层实现相同的目标但你必须拉更多的杠杆才能让它发挥作用。

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

于 2008-09-13T16:59:40.767 回答
12

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

我们需要 SMART 模型、THIN 控制器和 DUMB 视图。

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

于 2013-09-25T09:01:14.000 回答
7

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

于 2008-09-13T17:52:26.973 回答
7

一定要把与授权/访问控制相关的东西放在控制器中。

模型都是关于您的数据的。验证、关系、CRUD、业务逻辑

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

控制器是关于控制哪些数据从您的模型到您的视图(以及哪个视图)以及从您的视图到您的模型。控制器也可以在没有模型的情况下存在。

我喜欢将控制器视为保安/接待员,他将客户(请求)引导到您向出纳员(查看)问题的适当柜台。出纳员(视图)然后从您从未见过的经理(模型)那里得到答案。您的请求然后返回给保安/接待员(控制器)并等到您被指示去另一个柜员(视图),他告诉您经理(模型)告诉他们的答案以回应其他柜员(视图)的问题.

同样,如果您想告诉出纳员(查看)某些事情,那么基本上会发生相同的事情,除了第二个出纳员会告诉您经理是否接受了您的信息。也有可能是保安/接待员(控制员)告诉您去远足,因为您无权告诉经理该信息。

因此,为了扩展这个比喻,在我刻板和不切实际的世界中,出纳员(观点)很漂亮但头脑空洞,并且经常相信你告诉他们的任何事情,保安/接待员有最低限度的礼貌,但不是很了解,但他们知道人们应该去哪里和不应该去,经理们真的很丑陋和卑鄙,但什么都知道,可以分辨什么是真的,什么不是。

于 2008-09-15T12:59:23.963 回答
4

有助于正确分离的一件事是避免“将局部变量从控制器传递到视图”反模式。而不是这个:

# 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”中的内容及其使用方式变得更加容易。它增加了控制器和视图之间的分离,而不会使它们变得更复杂。

于 2008-09-15T14:54:19.490 回答
2

嗯,这有点取决于逻辑必须处理的内容......

通常,将更多东西推入模型是有意义的,而控制器则很小。这可确保您可以在任何需要访问模型表示的数据的地方轻松使用此逻辑。视图应该几乎不包含任何逻辑。所以真的,总的来说,你应该努力做到这一点,这样你就不会重复自己。

此外,快速浏览一下 google 会发现一些更具体的例子来说明去哪里。

模型:验证要求、数据关系、创建方法、更新方法、销毁方法、查找方法(注意,你应该不仅有这些方法的通用版本,而且如果有你经常做的事情,比如用红色找人姓氏的头发,那么你应该提取那个逻辑,这样你所要做的就是调用 find_redH_by_name("smith") 或类似的东西)

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

控制器:这是数据处理的地方。来自互联网:“控制器的目的是响应用户请求的操作,获取用户设置的任何参数,处理数据,与模型交互,然后将请求的数据以最终形式传递给看法。”

希望有帮助。

于 2008-09-13T16:33:54.853 回答
0

简单来说,通常, 模型将具有与表相关的所有代码,它们的简单或复杂关系(将它们视为涉及多个表的 sql 查询),使用业务逻辑操作数据/变量以达到结果.

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

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

与这些的任何重大偏差都会对该部分造成不必要的压力,并且整体应用程序性能可能会受到影响。

于 2016-09-01T15:43:58.690 回答
-1

测试,测试......在模型中加入尽可能多的逻辑,然后你就可以正确地测试它。单元测试通过测试模型来测试数据及其形成方式,功能测试通过测试控制器来测试数据的路由或控制方式,因此你无法测试数据的完整性,除非它在该模型。

j

于 2009-02-03T07:39:38.373 回答