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

时间:2008-09-13 16:18:01

标签: ruby-on-rails ruby model-view-controller

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

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

10 个答案:

答案 0 :(得分:168)

MVC

控制器:将代码放在这里与解决用户想要的内容有关,并决定要给他们什么,确定他们是否已登录,是否应该查看某些数据等最后,控制器查看请求并确定要显示的数据(模型)和要呈现的视图。如果您对代码是否应该进入控制器存在疑问,那么它可能不应该。保留控制器skinny

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

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

答案 1 :(得分:34)

添加到pauliephonic的答案:

帮助:使创建视图更容易的功能。例如,如果您总是迭代小部件列表以显示其价格,请将其放入帮助程序(以及实际显示的部分)。或者,如果你有一块你不想让视线混乱的RJS,那就把它放到帮手里。

答案 2 :(得分:13)

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

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

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

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

答案 3 :(得分:11)

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

  

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

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

答案 4 :(得分:7)

答案 5 :(得分:7)

将与授权/访问控制相关的内容放入控制器中。

模型都与您的数据有关。验证,关系,CRUD,业务逻辑

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

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

我喜欢将控制器视为保安人员/接待员,他将客户(请求)引导到您询问出纳员(查看)问题的相应柜台。出纳员(查看)然后去找一个你从未见过的经理(模特)的答案。你的请求然后回到保安/接待员(控制器)并等到你被指示去另一个出纳员(查看)谁告诉你经理(模型)告诉他们回答其他出纳员(查看)问题的答案。

同样,如果你想告诉柜员(查看)一些事情,那么大致相同的事情会发生,除非第二名出纳员会告诉你经理是否接受了你的信息。保安/接待员(控制人)也可能告诉您加息,因为您无权告知经理该信息。

所以为了扩展这个比喻,在我刻板的和不切实际的世界里,出纳员(观点)很漂亮但是空头而且往往相信你告诉他们的任何事情,保安/接待员都是极端礼貌但不是很了解但他们知道哪里人们应该而且不应该去,管理者真的很丑陋,但他们知道一切,能说出什么是真的,什么不是。

答案 6 :(得分: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”中的内容以及如何使用它。它增加了控制器和视图之间的分离,而不会使它们变得更复杂。

答案 7 :(得分:2)

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

通常情况下,将更多内容推入模型,使控制器变小是很有意义的。这可确保您可以从需要访问模型所代表的数据的任何位置轻松使用此逻辑。视图应该几乎不包含任何逻辑。所以,一般来说,你应该努力做到这一点,这样你就不要重复自己了。

此外,谷歌的一小部分内容揭示了更具体的例子。

模型:验证要求,数据关系,创建方法,更新方法,破坏方法,查找方法(请注意,您不仅应该拥有这些方法的通用版本,而且如果您有很多事情需要做很多事情,比如查找有姓红头发的人,那么你应该提取那个逻辑,这样你所要做的就是调用find_redH_by_name(“smith”)或类似的东西)

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

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

希望有所帮助。

答案 8 :(得分:0)

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

控制器将拥有针对所请求作业的相关模型的代码/指针。

观看次数将接受用户输入/互动并显示结果回复。

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

答案 9 :(得分:-1)

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

Ĵ