何时在控制器和视图之间分离条件/逻辑?

时间:2011-07-29 15:46:59

标签: ruby-on-rails

我注意到我的视图中有一些简单的逻辑和条件(if ... else),而不是控制器。它们不一定是复杂的条件,因为它们只是根据输出输出不同的文本。

我只是不知道如何确定何时放入控制器,什么时候不要放入控制器。有任何性能问题吗?

感谢。

5 个答案:

答案 0 :(得分:1)

这不是性能问题。这是一个维护问题。例如,如果您在视图中有逻辑,那么为系统中的逻辑编写测试并不容易。如果它在控制器中,那么编写测试就很容易了。如果你有很多逻辑视图,那么webform将再次出现问题。

答案 1 :(得分:1)

在视图中有一些逻辑本身并不坏,只要你有控制器的角色(做什么和要显示什么)和视图(如何显示)分开。这有助于您获得可理解和可维护的代码。旁注:模型是所有“怎么做”的地方。

控制器是用户与应用程序及其模型交互的位置,视图是显示给用户的内容。根据经验,如果你必须在视图中以某种方式回应用户的输入,那么你的逻辑就在错误的位置。

良好的观点逻辑:

<p><%= @user.name -%> <%= '(admin)' if @user.admin? -%></p>
<ul>
<% @user.documents.each do |document| %>
  <%= render "/documents/#{document.format}_list", :document => document %>
<% end %>
</ul>

这很糟糕:

<% @user = User.find params[:id] %>

答案 2 :(得分:0)

我实际上只花了一些时间在我的工作项目中,将我的模板中的模板声明用于我正在制作的mvc(或至少有志成为mvc)网站。

如果你想坚持mvc的最严格意义,那么你的视图中不应该有任何逻辑结构。所以即使在渲染一个集合时 - 让我们说一个列表 - 你应该有一个foreach循环(来自你的控制器)有一个模板的参数,并反复调用该片段。我不喜欢这样做的事情是,如果你不小心如何聚合你的最终复合视图,它会导致效率非常低效的代码,这个视图包含你所有的视图。如果您正在使用的模板库具有渲染方法b / c,如果您正在以这种方式执行操作,则尤其如此 - 您可能会一遍又一遍地调用“渲染”。基本上,您可能最终会进行字符串聚合,而不是使用单个流构建视图。

所以 - 我一直在做的是,我有模板文件,我实际上已经标记为“控制器”。所以,在这里,我将有IF / FOREACH或其他逻辑结构,并调用适当的子模板/子视图。我认为没有人说你的模板文件必须只是一个视图。我认为范例是你的VIEW必须没有逻辑结构。通过制作实际上是控制器而不是视图片段的模板文件来隔离这些逻辑结构,应该提供一个愉快的媒介。

示例(使用谷歌闭包模板库)

混合逻辑和视图(不好......但在你以这种方式构建复杂视图之前,你并没有真正找到原因):

/**
 *
 * Template description
 *
 * @param paramA description of paramA 
 * @param paramB description of paramB
 * @param paramC description of paramC
 *
 *
 */
{template .myTemplate}
     <div class="{$paramA}">
       {if $paramC}
         <span class="{$paramB}">Some content</span>
       {/if}
     </div>
{/template}

分离逻辑和视图。请注意控制器模板文件如何不向视图添加任何内容。它只是调用另一个模板。

控制器模板文件:

/**
 *
 * Template description
 *
 * @param condition description of condition
 * @param parameters parameters to call subtemplate with
 *
 */
{template .myTemplate}
     {if $condition}
          {call .getTemplForCondition data="$parameters" /}
     {else}
          {call .getTempl data="$parameters" /}
     {/if}
{/template}

然后是模板文件......现在视图中没有逻辑......

/**
 *
 * Template description
 *
 * @param paramA description of paramA 
 * @param paramB description of paramB
 *
 */
{template .getTemplForCondition}
     <div class="{$paramA}">
         <span class="{$paramB}">Some content</span>
     </div>
{/template}

/**
 *
 * Template description
 *
 * @param paramA description of paramA 
 *
 */
{template .myTemplate}
     <div class="{$paramA}"></div>
{/template}

答案 3 :(得分:0)

问题不是表现,而是关注点的分离。控制器应包含业务逻辑;例如,用于确定在给定用户输入的情况下要获取哪些数据的逻辑。

然后控制器将数据传递给视图。视图中的逻辑应仅关注如何向用户显示数据。某些事情需要多元化吗?是否应根据返回的数据显示/隐藏某些UI元素?这些事情的逻辑很简单,应该是观点的责任。

根据您的问题,只要视图中的简单逻辑不是业务逻辑,您似乎就有了正确的想法。

答案 4 :(得分:0)

在Rails术语中,该模型充当多层应用程序中的中间层。把你的逻辑放在模型中而不是控制器或视图中。如果视图或控制器需要对要显示的内容做出选择,请询问模型是否可以执行某些操作并在模型中实现该功能。

<% if @model.sais_its_ok %>
  OK Go ahead
<% else %>
  Sorry, Not allowed!
<% end %>

这种情况的最佳选择是使用视图助手,但在控制器中可以询问模型。 实际上,控制器一直在询问模型,而你甚至没有意识到它。

他们会告诉模型保存数据。该模型将运行验证,如果它们失败,它们将告诉控制器它无法执行此操作,模型甚至会告诉控制器错误哈希中的原因(和vuiews)。

如果您使用其他语言来表达,请记住模型是中间层,控制器只需要在中间层(模型和视图)之间传递数据。这就是真正的MVC架构。

来自@jimworm的回复在他的回复中完美地证明了这一点,询问模型是否是管理员?