<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>MaiZardAyumi (Dearest)</title>
    <link>https://ruby-china.org/MaiZardAyumi</link>
    <description></description>
    <language>en-us</language>
    <item>
      <title>Slimming-Controllers </title>
      <description>&lt;p&gt;看到一篇文章想看看大家的意见，试着翻译过来分享一下~ ， &lt;a href="http://tutorials.jumpstartlab.com/topics/controllers/slimming_controllers.html" rel="nofollow" target="_blank" title=""&gt;原文地址&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="Slimming-Controllers"&gt;Slimming-Controllers&lt;/h2&gt;
&lt;p&gt;控制器是很笨的，他们仅仅只是一个模型层和视图层的连接器，用来处理关于请求的信息，然后把他们发送到他们应该去的地方。&lt;/p&gt;
&lt;h2 id="Pushing Responsibility Down the Stack (不知道怎么翻译。。)"&gt;Pushing Responsibility Down the Stack (不知道怎么翻译。。)&lt;/h2&gt;
&lt;p&gt;事实上，大多数的控制器做的不仅仅是简单地处理请求。它们看管数据，响应许多失败条件，还展示业务逻辑，这是不好的。&lt;/p&gt;

&lt;p&gt;为什么这是不好的呢？因为控制器会使逻辑掉入陷阱。它们比模型更加难以测试，并且这些逻辑几乎是不可能修复的。直接把业务逻辑放在控制器里面违背了 Single 
Responsibility Principle.&lt;/p&gt;

&lt;p&gt;那让我们来看看咱们减少控制器的复杂度。其中一个方法是领域逻辑放到模型层里面。&lt;/p&gt;
&lt;h3 id="限制逻辑判断"&gt;限制逻辑判断&lt;/h3&gt;
&lt;p&gt;许多控制器变得糟糕的原因是因为参数判断。“如果这个参数存在，干什么，否则，查找另一个参数，如果那个参数存在，干什么”等等。&lt;/p&gt;

&lt;p&gt;Rails 把 REST 构造成七个方法，但是不意味着你的控制器就局限于此。如果你发现一个动作有超过 8 行代码的话，把他提取出来放到一个另外
的控制器方法中。&lt;/p&gt;

&lt;p&gt;仅仅是这样还是不够的，这是一个你能够把逻辑放到 model 里面的标志。没有一个合适的 model？创建一个！可能它是一个门面，可能是一个工人。
不管怎样，把这些逻辑放到模型层里面，然后在控制器里面使用。&lt;/p&gt;

&lt;p&gt;然后去掉你的定制的方法。就想我们说的，Rails 并没有把你限制在这七个 RESTful 方法里。但我们朝这个方向努力是非常好的。&lt;/p&gt;
&lt;h3 id="看看index"&gt;看看 index&lt;/h3&gt;
&lt;p&gt;在这个&lt;code&gt;index&lt;/code&gt;的实现中，我们把所有的逻辑放到了模型里面。在这个例子中，我们可能想要进一步的重构模型，这可能太复杂了，但是这很好的说明了
我们正在谈论的步骤。&lt;/p&gt;

&lt;p&gt;在这个控制器里面，我们有：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;
    &lt;span class="vi"&gt;@articles&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vi"&gt;@tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search_by_tag_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:tag&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
 &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我们的目标是根据提供的&lt;code&gt;tag&lt;/code&gt;找到&lt;code&gt;articles&lt;/code&gt;。我们在 model 里面有如下定义：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search_by_tag_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tag_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;tag_name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;blank?&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;scoped&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="n"&gt;tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Tag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_by_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tag_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;tag&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;articles&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[[],&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果传入的 tag 的名称是&lt;code&gt;nil&lt;/code&gt;或者空字符串，这个方法会返回 &lt;code&gt;Article.scoped&lt;/code&gt;，这是&lt;code&gt;Article.all&lt;/code&gt;的一个懒查询版本。如果提供了一个名称，
就会找到这个名称的 tag 然后返回所有的这个 tag 的 articles 和这个 tag，如果没有找到这个名称，会返回一个空数组和 nil。&lt;/p&gt;

&lt;p&gt;尽管这不是最复杂的逻辑，但是在控制器里面测试它依然需要很多工作。打开&lt;code&gt;article_spec.rb&lt;/code&gt;文件看看这些单元测试是多么简单。&lt;/p&gt;
&lt;h3 id="接口"&gt;接口&lt;/h3&gt;
&lt;p&gt;好的面向对象设计依赖于低耦合 - 拥有只有尽可能少的一部分联结在一起的明确的角色和职责。&lt;/p&gt;

&lt;p&gt;根据 MVC 架构，Rails 里面的控制器和视图是独立的职责。他们应该是分开的部分，仅仅只通过一些设计良好的连接点来进行交流。&lt;/p&gt;

&lt;p&gt;但 Rails 不是这么做的。&lt;/p&gt;

&lt;p&gt;你怎么在视图里面获取控制器的数据呢？实例变量。看看下面这个例子， &lt;code&gt;ArticlesController&lt;/code&gt;&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ArticlesController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;
    &lt;span class="vi"&gt;@article&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;#...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;当 Rails 为&lt;code&gt;show&lt;/code&gt;动作渲染视图时，复制了控制器里面的实例变量到渲染的视图中，这两个部分很显然耦合了。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;OPINION: 无论何时你在 Ruby 你使用实例变量，问问你自己：“是否有更好的方法？”答案总是“是”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="限制实例变量"&gt;限制实例变量&lt;/h3&gt;
&lt;p&gt;一个常规的控制器动作有一个实例变量。许多动作有两个或三个实例变量，但是如果你有更多的话，这是一个你缺少领域抽象的信号。&lt;/p&gt;

&lt;p&gt;这些对象之间必要的“联系”是什么？为什么它们都属于同一个页面？无论原因是什么，这可能是一个领域对象。看看 &lt;a href="http://tutorials.jumpstartlab.com/topics/models/facade_pattern.html" rel="nofollow" target="_blank" title=""&gt;Facade pattern&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;我们频繁地使用 accessor 方法。我们怎么为控制器写 accessors？这是非常建的的，让我们再来看看这个控制器和动作&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ArticlesController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;
    &lt;span class="vi"&gt;@article&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;#...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="视图模板用法"&gt;视图模板用法&lt;/h4&gt;
&lt;p&gt;在视图模板中，我们像这样访问这个对象：&lt;/p&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="vi"&gt;@article.title&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果我们不使用实例变量，我们怎么做呢？这样怎么样：&lt;/p&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我们怎样使它生效呢？Rails 将有一个叫做 &lt;code&gt;article&lt;/code&gt; 的 helper 方法。没问题。&lt;/p&gt;
&lt;h5 id="实现一个Helper Method"&gt;实现一个 Helper Method&lt;/h5&gt;
&lt;p&gt;控制器。我们能够添加一个&lt;code&gt;article&lt;/code&gt;方法：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ArticlesController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;
    &lt;span class="vi"&gt;@article&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;article&lt;/span&gt;
    &lt;span class="no"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;#...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我们没有必要传递&lt;code&gt;params&lt;/code&gt;到我们的新方法，因为现在仍然在控制器上下文里面，所以能够访问常规的&lt;code&gt;params&lt;/code&gt;，就像任何其他的动作一样。&lt;/p&gt;

&lt;p&gt;加载视图，没有起作用。仅仅在控制器里面定义方法是不够的，我们必须把它作为一个 helper 暴露给视图。&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ArticlesController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;
    &lt;span class="vi"&gt;@article&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;article&lt;/span&gt;
    &lt;span class="no"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;helper_method&lt;/span&gt; &lt;span class="ss"&gt;:article&lt;/span&gt;

  &lt;span class="c1"&gt;#...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;现在视图生效了。但是&lt;code&gt;show&lt;/code&gt;动作怎么办呢？如果视图现在是访问&lt;code&gt;article&lt;/code&gt; helper，让我们去掉这些实例变量：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ArticlesController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;article&lt;/span&gt;
    &lt;span class="no"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;helper_method&lt;/span&gt; &lt;span class="ss"&gt;:article&lt;/span&gt;

  &lt;span class="c1"&gt;#...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果你喜欢，你甚至可以删掉&lt;code&gt;show&lt;/code&gt; 方法。&lt;/p&gt;
&lt;h4 id="The new Action"&gt;The new Action&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;show&lt;/code&gt; 动作是简单的，那么&lt;code&gt;new&lt;/code&gt;呢？&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def new
    @article = Article.new
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在视图模板里面我们希望有一个叫做&lt;code&gt;@article&lt;/code&gt;的新的，空的对象。如果我们用这个存在的 helper，它会试图做一个机遇&lt;code&gt;params[:id]&lt;/code&gt;的查找。&lt;/p&gt;

&lt;p&gt;没问题，在这个 helper 方法里添加一些对&lt;code&gt;params[:id]&lt;/code&gt;的响应逻辑：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ArticlesController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;new&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;article&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="no"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="no"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;helper_method&lt;/span&gt; &lt;span class="ss"&gt;:article&lt;/span&gt;

  &lt;span class="c1"&gt;#...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我们去掉了&lt;code&gt;new&lt;/code&gt;方法里面的代码，然后改变了模板视图来使用 helper 而不是实例变量。&lt;/p&gt;
&lt;h4 id="性能考虑"&gt;性能考虑&lt;/h4&gt;
&lt;p&gt;哇哦，你注意到当查找&lt;code&gt;show&lt;/code&gt;视图时的控制台日志了吗，如果你没有，现在看一看。好像我们进行了一大推查询，每次我们调用 hepler 时。&lt;/p&gt;

&lt;p&gt;不是问题：我们将使用一个实例变量在第一次请求后来记住这个对象&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ArticlesController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;article&lt;/span&gt;
    &lt;span class="vi"&gt;@cached_article&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="no"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="no"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;为什么这个实例变量叫做&lt;code&gt;@cached_article&lt;/code&gt;？我不想用&lt;code&gt;@article&lt;/code&gt;，否决有些人又会继续开始在视图里面使用实例变量，如果你想访问
article，你应该使用我已经定义的访问方法，我强烈鼓励你这么做。&lt;/p&gt;

&lt;p&gt;可能你甚至想使代码更简洁，你看了看逻辑并且想把它放到模型层里面。好主意！你可能会创建像这样的东西：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Article&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;find_or_build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;input_id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;present?&lt;/span&gt;
      &lt;span class="no"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="no"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;但这是没有必要的，你能使用在&lt;code&gt;ActiveRecord&lt;/code&gt;里面内置的&lt;code&gt;find_or_initialize_by&lt;/code&gt;方法：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ArticlesController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;article&lt;/span&gt;
    &lt;span class="vi"&gt;@cached_article&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="no"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_or_initialize_by_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果找到了，&lt;code&gt;find_or_initialize_by&lt;/code&gt;方法会返回该记录，否则会返回这个类的一个新的实例，在这个例子中是&lt;code&gt;Article&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;不知道大家怎么看这篇文章的观点？我现在看到过的代码都是创建实例变量，而这个文章说不要使用实例变量。&lt;/p&gt;</description>
      <author>MaiZardAyumi</author>
      <pubDate>Tue, 11 Apr 2017 18:45:54 +0800</pubDate>
      <link>https://ruby-china.org/topics/32751</link>
      <guid>https://ruby-china.org/topics/32751</guid>
    </item>
    <item>
      <title>按照 hoemland install 操作，make start 之后下一步该做什么呀？</title>
      <description>&lt;p&gt;对于部署这块概念不是很熟，能给个提示吗&lt;img src="https://l.ruby-china.com/photo/2017/e6e813e0213ed7c2845f93df47b83644.png!large" title="" alt=""&gt;&lt;/p&gt;</description>
      <author>MaiZardAyumi</author>
      <pubDate>Thu, 06 Apr 2017 22:25:35 +0800</pubDate>
      <link>https://ruby-china.org/topics/32716</link>
      <guid>https://ruby-china.org/topics/32716</guid>
    </item>
    <item>
      <title>怎么通过变量 去动态的取得 变量名？</title>
      <description>&lt;p&gt;比如我有 3 个数组，a1, a2, a3。要怎么样实现&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
   &lt;span class="n"&gt;ai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
        &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;
   &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;，就这种动态取得变量的效果&lt;/p&gt;</description>
      <author>MaiZardAyumi</author>
      <pubDate>Fri, 24 Mar 2017 15:51:34 +0800</pubDate>
      <link>https://ruby-china.org/topics/32627</link>
      <guid>https://ruby-china.org/topics/32627</guid>
    </item>
    <item>
      <title>请问&lt;%= form_tag ('/posts') do -%&gt; 后面那个- 有什么用？</title>
      <description>&lt;p&gt;&lt;img title=":smile:" alt="😄" src="https://twemoji.ruby-china.com/2/svg/1f604.svg" class="twemoji"&gt; &lt;/p&gt;</description>
      <author>MaiZardAyumi</author>
      <pubDate>Thu, 23 Mar 2017 09:59:39 +0800</pubDate>
      <link>https://ruby-china.org/topics/32614</link>
      <guid>https://ruby-china.org/topics/32614</guid>
    </item>
    <item>
      <title>Ruby 文档怎么看？</title>
      <description>&lt;p&gt;比如我想找 block，或者  -&amp;gt; 这个符号，但是都搜索不到 &lt;a href="http://ruby-doc.org/core-2.4.0/" rel="nofollow" target="_blank"&gt;http://ruby-doc.org/core-2.4.0/&lt;/a&gt;&lt;/p&gt;</description>
      <author>MaiZardAyumi</author>
      <pubDate>Tue, 21 Mar 2017 21:52:16 +0800</pubDate>
      <link>https://ruby-china.org/topics/32600</link>
      <guid>https://ruby-china.org/topics/32600</guid>
    </item>
    <item>
      <title>请问 Railscast 还能看吗？好像都是好多年以前的</title>
      <description>&lt;p&gt;会不会和现在的 rails 有很大区别？&lt;/p&gt;</description>
      <author>MaiZardAyumi</author>
      <pubDate>Thu, 19 Jan 2017 10:50:40 +0800</pubDate>
      <link>https://ruby-china.org/topics/32172</link>
      <guid>https://ruby-china.org/topics/32172</guid>
    </item>
  </channel>
</rss>
