【问题标题】:Rails Model, View, Controller, and Helper: what goes where?Rails 模型、视图、控制器和助手:什么去哪里?
【发布时间】:2010-09-08 19:22:44
【问题描述】:

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

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

【问题讨论】:

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


    【解决方案1】:

    添加到 pauliephonic 的答案:

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

    【讨论】:

    【解决方案2】:

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

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

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

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

    【讨论】:

      【解决方案3】:

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

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

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

      【讨论】:

        【解决方案4】:

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

        j

        【讨论】:

          【解决方案5】:

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

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

          【讨论】:

          • 嗯……嗯。您能否为您何时执行此操作添加一些充分的理由/场景。这打破了 KISS 和 YAGNI 并且非常臭(只是再折腾一个陈词滥调)
          • 1) Rails 做了很多魔术来将控制器的实例变量复制到您的视图实例。 2)建议的实现也只加载 foo 如果它被访问,这可能会在某些时候节省一些工作。不过,重要的答案确实是 1)。
          • 叹息 这太可怕了。 Rails 实例变量共享是一个特性而不是反模式。它是一种无处不在的、低心理开销的语法糖,很少会导致现实世界的问题。如果你不喜欢它,很好,但是用巴洛克式的非标准结构围绕它进行编码会使事情变得更糟。在这种情况下,您实际上使 foo 成为全局(无论如何每个控制器)变量。试图通过显着增加范围来纠正对变量范围的滥用是非常具有讽刺意味的。
          • 我不买它,dasil003。 foo@foo 的范围是相同的——它们都被限定为 对。此外,通过使用 getter 版本,我可以更改 Foo 对象的查找/存储/缓存方式,而无需更改视图访问它的方式。
          • 我认为您的意思是“传递实例变量”反模式。实例 var 将泄漏整个渲染的状态,即使在深度嵌套的部分中也是如此。您的解决方案也会泄漏状态,但比实例 var 稍好,因为它不允许重新分配。传递一个本地实际上是最好的,因为它就像调用一个方法;局部看不到局部。见this answer
          【解决方案6】:

          MVC

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

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

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

          【讨论】:

          • 人们开始远离胖模型。我喜欢将我的模型视为一种数据结构。然后我编写了一些 Ruby 对象来实现该行为,并使用模型对其进行初始化(它将模型视为数据,就像您将字符串和数组视为 Rails 之外的对象中的数据一样)。 Here's 一个带有这种技术示例的好视频。
          • @AdamDonahue 我不确定肥胖的任何东西都可以被视为一件好事。大量的责任最好属于服务。
          【解决方案7】:

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

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

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

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

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

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

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

          【讨论】:

            【解决方案8】:

            Rails 的方式是拥有skinny controllers and fat models

            【讨论】:

              【解决方案9】:

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

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

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

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

              【讨论】:

              • 这是一个很好的答案:)
              【解决方案10】:

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

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

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

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

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

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

              希望对您有所帮助。

              【讨论】:

                猜你喜欢
                • 2016-07-23
                • 2010-11-13
                • 2011-05-26
                • 2010-12-08
                • 1970-01-01
                • 1970-01-01
                • 2011-10-04
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多