【问题标题】:How to DRY code in controllers and helpers for rendering the right way?如何在控制器和助手中干燥代码以正确呈现?
【发布时间】:2013-09-21 08:29:40
【问题描述】:

我正在使用 Ruby on Rails 3.2.13,我想在控制器和视图中干燥(不要重复自己)我的代码。也就是此时……

...在我的控制器中,我有:

# ArticlesController

def index
  @articles = ...
  ...
  case ...
  when ... then render(:partial => 'partial_for_index', :object => @articles, :as => 'articles', ...)
  else render :index
  end
end

def show
  @article = ...
  ...
  case ...
  when ... then render(:partial => 'partial_for_show', :object => @article, :as => 'article', ...)
  else render :show
  end
end

...在我的助手中我有:

# ArticlesHelper

def render_partial_for_index(articles, ...)
  articles.map { |article| render_partial_for_show(article, ...) }.join('').html_safe
end

def render_partial_for_show(article, ...)
  render(:partial => 'partial_for_show', :object => article, :as => 'article', ...)
end

...在我看来,我有:

# articles/_partial_for_index.html.erb
<%= render_partial_for_index(@articles, ...) %>

# articles/_partial_for_show.html.erb
<%= article.title %> created at <%= article.created_at %>

为了干燥我的代码,我想直接在控制器中使用辅助方法(注意:我知道这种方法破坏了 MVC 模式,但这只是我的目标和应该做的一个例子使问题更容易理解),这样:

# ArticlesController

include ArticlesHelper

def index
  @articles = ...
  ...
  case ...
  when ... then render_partial_for_index(@articles, ...)
  else render :index
  end
end

def show
  @article = ...
  ...
  case ...
  when ... then render_partial_for_show(@article, ...)
  else render :show
  end
end

这样我可以删除_partial_for_index.html.erb 视图文件,因为它不再被使用,并且代码在整个应用程序中DRYed一致。然而,虽然控制器 show 操作按预期工作,但控制器 index 操作却没有,因为我收到了 DoubleRenderError 错误,因为多个 render 方法在 render_partial_for_index 辅助方法中运行。

简而言之,我想使用尽可能少的语句进行渲染。我如何/应该干燥我的代码以达到我的目标?也就是说,我怎样才能以正确的方式在视图和控制器中保持render_partial_for_indexrender_partial_for_show 方法的可用性?

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-3 rendering dry


    【解决方案1】:

    其实我不喜欢你的控制器,因为它混合了应该属于视图的逻辑,而 render_blah 方法使事情变得不必要地复杂。

    我更喜欢这种风格:

    # ArticlesController
    def index
      @articles = ...
    end
    
    def show
      @article  = ...
    end
    
    # views/articles/index.html.erb
    <% @articles.each do |article| %>
      <%= render partial: 'article', locals: {article: article}
    <% end %>
    
    # views/articles/show.html.erb
    <%= render partial: 'article', locals: {article: @article}
    
    # views/articles/_article.html.erb
    <%= article.title %>
    <%= article.body  %>
    # blah blah
    

    同样的效果。干燥机代码。更清晰的逻辑。不需要助手。

    【讨论】:

    • 我在问题中提到的部分模板在我的应用程序中越来越多地使用,因此我在辅助方法中提取了相关的渲染代码,以免重复整个render partial: ...语句并保留内容持续的。由于控制器操作中需要完全相同的渲染(并且我不会重复render partial: ...),所以我想即使在那里也使用相同的语句。 注意:问题的重点是方法的组织和可访问性,而不是视图文件的内容。
    • 那么,我怎样才能保持逻辑分离但干燥呢?
    • 我更新了问题。也许事情更清楚了,因为我想这样做......
    • 有一个_article 部分供您在任何地方重复使用。如果你使用一个助手,你仍然需要用变量来喂它。我怀疑这比直接使用render 更简单
    • 假设你有一个小部件来显示最近的文章,你可以制作一个小部件部分或小部件助手,它调用这个部分。此外,我不明白您的控制器中的情况是什么,看起来不是惯例。
    猜你喜欢
    • 1970-01-01
    • 2011-09-02
    • 1970-01-01
    • 1970-01-01
    • 2019-03-09
    • 1970-01-01
    • 2020-07-27
    • 2013-09-16
    • 1970-01-01
    相关资源
    最近更新 更多