从视图中调用模型类方法是否可以

时间:2014-09-22 23:41:59

标签: ruby-on-rails ruby-on-rails-4 spree

当我遇到一个创作它的宝石时,我正在为我的狂欢商店实施幻灯片放映。在ReadMe文件的一部分中,我注意到它直接从视图调用模型类方法:https://github.com/priviterag/spree_slider#or-roll-your-own

以下是代码:

<% if Spree::Slide.published.count > 0 %>
  <section id="slideshow">
    <ul class="slide">
      <% Spree::Slide.published.order('position ASC').each do |s| %>
        <li>
          <h1><%= s.slide_name %></h1>
          <%= link_to image_tag(s.slide_image.url), url_for(s.slide_link) %>
        </li>
      <% end %>
    </ul>
    <a title="<%= t(:previous) %>" class="slider-prev"><%= t(:previous)%></a>
    <a title="<%= t(:next) %>" class="slider-next"><%= t(:next) %></a>
  </section>
<% end %>

我使用自己的滑块做了同样的事情,但之后标记了模型调用作为移动到相关控制器(稍后会有几个)的东西。但是,实际上,当从这样的视图中直接调用模型时,它似乎是最独立,最容易理解和维护的。

我总是一直认为View直接访问Model类给了好的程序员噩梦。但是在这种情况下,直接从视图中获取数据OK?为什么或为什么不呢?

2 个答案:

答案 0 :(得分:2)

我不会,主要是因为你的观点正在做出一堆假设,这些假设在以后会发生变化。您的观点假设它正在使用:

  • 一个ActiveRecord类,
  • 包含某些表格列
  • 与其他对象一起直接调用。
  • 的属性

以下是我对观点的看法:

<% if slides.count > 0 %>
  <section id="slideshow">
    <ul class="slide">
      <% slides.each do |s| %>
        <li>
          <h1><%= s.name %></h1>
          <%= link_to image_tag(s.image_url), url_for(s.link) %>
        </li>
      <% end %>
    </ul>
    <a title="<%= t(:previous) %>" class="slider-prev"><%= t(:previous)%></a>
    <a title="<%= t(:next) %>" class="slider-next"><%= t(:next) %></a>
  </section>
<% end %>

主持人:

# eg. app/presenters/slide_presenter.rb
class SlidePresenter
  extend Forwardable
  def initialize(slide)
    @slide = slide
  end

  def_delegator :@slide, :name, :slide_name
  def_delegator :@slide, :link, :slide_link

  def image_url
    @slide.slide_image.url
  end
end

控制器动作本身:

slides = Spree::Slide.published
                     .order('position ASC')
                     .map {|s| SlidePresenter.new(s) }
render 'theview', locals: { slides: slides }

使用Presenter而不是直接在视图中使用模型的好处是它限制了模型的使用方式。您不必调用ActiveRecord模型中的任何数百个方法(包含参数中的所有变量),而是确切地知道它是如何被使用的,因为您只在演示者上定义了四种方法。

(隐藏演示者背后的模型行为还会为您提供一个不会改变的接口:也就是说,更改模型意味着更改演示者本身的内容,但不是所有视图使用演示者。)

在上面的示例中,我不是控制器中直接ActiveRecord业务的忠实粉丝,但您可以选择将其移动到类似FetchOrderedSlides服务类或辅助方法的东西,进一步限制数百个的已知用途在代码库的非常具体的部分中滑动到少数几个方法。

答案 1 :(得分:1)

传递给Rails视图的大多数内容都是AREL代理对象,通过它们可以在视图中呈现数据时获取和返回数据。在这方面,&#34;直接从视图中获取数据&#34;如果您的问题是关于事件的排序和实际发生的事情,那么这不仅是可接受的,而且是常态。

但我认为你所得到的是:为什么要将视图与模型隔离?什么不好的事情发生在它们不是?

有很多与MVC相关但不同的模式。 (例如http://en.wikipedia.org/wiki/Model_View_ViewModel)MV就是这样一个例子。在MV中,视图知道模型的所有内容,但模型不了解视图。您可以使用MV模式编写整个应用程序。也许是一个小的。 :P您发布的示例看起来像MV。

老实说,我觉得MVC dos和donts很快就会从软件架构师的角度获得firebrand规则的律师资格。它让我感到沮丧。人们应该冷静下来,考虑他们的选择。如果你没有,我建议阅读Martin Fowler的Refactoring,我认为阅读有关MVC和Presentation Model的历史也会很有成效。 MVC并不是城里唯一的游戏。你应该在有用的时候打破课程,但是当你过度工作时也要崩溃和合并课程。在那种情况下,我认为有时MV是足够的,而MVC是过度的。粘贴到网络上的一些小例子可能就是这样的,尽管有些人在将它们移植到更大的应用程序时可能会对它们进行一点点的解释。

MVC可以处理这样一种情况:应用程序的复杂性使得分离出每个微不足道的小问题是管理所涉及的大量代码的唯一方法。 MVC的假设是你的应用程序将变得庞大而复杂。想想像Microsoft Word这样的应用程序。在该上下文中,您可能具有MDI(多文档界面)场景,其中存在需要通过事件保持同步的同一模型的多个视图。您可能有不同类型的模型可以以相同的方式呈现。事实上,如果你能想象一个扳手投入工作,非常复杂的应用程序需求可能会抛出它。所以你可以选择MV并开始使用,最终它会开始变得混乱。您可能拥有大量的Controllery逻辑,例如连接事件回调和编排请求处理内部视图(如无MVC的PHP),此时您可能希望将其分解以更好地管理它。

你提到的噩梦很可能是那些开​​始使用MV并且最终遇到更简单模式限制的开发人员,并且因为huuuuge数量的技术债务交换到MVC或其他东西而陷入死胡同。鉴于必须应对HTTP及其特性的本质,以及HTML和CSS的复杂性以及您必须处理的所有内容,以及数据库和持久性,更不用说业务逻辑,我认为MVC几乎总是适用于Web应用程序。

专注于只有几个类来处理的小宝石,满足特定需求,其组件视图不可能在任何其他上下文中重用?我不会那么严格。