【问题标题】:Rendering other controllers' templates (Ruby on Rails)渲染其他控制器的模板(Ruby on Rails)
【发布时间】:2009-12-23 22:59:45
【问题描述】:

我正在构建一个示例站点来熟悉 RoR。我在一定程度上遵循了“Agile Web Development with Rails”一书,现在我正在试验并将其用作参考,但是我无法找到我的问题的答案。

我有两种感兴趣的模式,一种是连锁超市,另一种是超市。显然,连锁超市有一堆超市。我要做的是获取单个连锁超市的基本“显示”页面,以显示属于它的超市列表。

我也不想重复自己(因为显然这是一件非常糟糕的事情),所以我想我可以使用“渲染”将超市的 index.html.erb 插入到 supermarketchain/show.html.erb 页面中,像这样:

<%= render :template => 'supermarkets/index' %>

但是,这在页面上产生了零输出。

我的下一个方法是使这个部分:

<div id="supermarket-list">
  <h1><%= I18n.t "supermarket.title" %></h1>

  <table>
    <% for s in @supermarkets %>
    <tr class="<%= cycle('list-line-odd', 'list-line-even') %>">
        <td> 
            <%= s.supermarketchain.name %>
        </td>
        <td>
            <%= s.address %>
        </td>
        <td class="list-actions">
            <%= link_to I18n.t("general.show"), s%> <br/>
            <%= link_to I18n.t("general.edit"), edit_supermarket_path(s) %> <br />
            <%= link_to I18n.t("general.delete"), s, :confirm => I18n.t("general.confirmation"), :method => :delete %>
        </td>
    </tr>
    <%end%>
  </table>
</div>

然后使用:

<% @supermarkets = Supermarket.all %>

<%= render :partial => 'supermarkets/supermarket' %>

将其插入超市连锁店的展示页面。

我想知道这是否是一个好习惯。在我看来,初始化一个供部分使用的变量似乎很奇怪,而我想要显示的是超市控制器的“索引”操作的确切结果。评论?

请询问任何需要的说明。

【问题讨论】:

    标签: ruby-on-rails ruby renderpartial


    【解决方案1】:

    在 Rails 中渲染来自其他控制器的部分是非常好的。通常,如果一个partial 并不真正属于任何一个特定的控制器,它就会被放入app/views/shared。在这种情况下,尽管我认为将部分保留在超市控制器中是有意义的。

    您可以通过以下方式对两个部分使用相同的部分supermarkets/_supermarket.html.erb。局部变量将具有可用的局部变量 supermarket

    # supermarketchain/show.html.erb
    <%= render :partial => "supermarkets/supermarket", :collection => @supermarketchain.supermarkets %>
    
    # supermarkets/show.html.erb
    <%= render :partial => "supermarket", :object => @supermarket %>
    

    【讨论】:

      【解决方案2】:

      你可以这样做

      <%= render :partial => 'supermarket', :collection => Supermarket.all, :as => :s %>
      

      每个超市都会调用一次partial,变量名为s

      【讨论】:

      • 谢谢!好吧,听起来更好。但是,为我想包含在其他模型页面中的每个模型制作一个部分是个好主意吗?我的主要问题是关于设计,而不是如何调用渲染。
      • 实际上,经过仔细检查,我相信您的建议要求我将部分更改为对单个项目进行操作,而目前它需要一个集合并对其进行迭代。我试过了,但没有用。你觉得我这样改代码更好吗?
      • 我认为你应该有一个单独的超市视图。 但是您不必替换当前的“多重”视图。相反,您可以在“多个”版本中使用您的单个视图。然后你就可以在你的代码上同时使用这两者了。
      【解决方案3】:

      好的,如果我没记错的话,你有一个连锁店列表,每个连锁店都有一个超市列表,对吧?你有两个模型之间的关联设置吗?因为如果你有的话,那只会简化事情。在这种情况下,假设您将模型从“supermarketchains”重命名为“chain”(清除任何混淆)。你可以像这样关联模型>

      has_many :超市

      在超市模式中。

      belongs_to :链

      从那里开始,这只是一个循环问题:

      <% if chain.supermarkets.count > 0 %>
      
      #Do stuff.
      
      <% end %>
      

      也就是说,如果您没有设置控制器来提取该信息,则可能需要额外的工作。

      【讨论】:

      • 我已经这样做了,但这可以说是重复自己的情况,我正在寻找一种方法来避免它:) 我只是在探索是否有“Rails”方式这样做是经过批准和良好测试的。
      【解决方案4】:

      我自己也为此苦苦挣扎,但发现它并没有真正被支持作为渲染部分的方式,而且由于我通常相信 Rails 开发人员约定,我认为这可能不是一个好主意。

      我认为在其中使用模板行不通,您可以使用render_to_string,但这看起来很老套,将来可能会让您更加头疼。

      另外,如果你想渲染一个集合,最好的方法是在控制器动作中设置实例变量,而不是在视图中..

      def index
        @supermarkets = Supermarket.all
      end
      

      然后在视图index.html.erb,调用:

      <%= render @supermarkets %>
      

      然后它将遍历数组的每个成员,并为每个成员呈现 views/supermarkets/_supermarket.html.erb,其中 'supermarket' 是部分可用的当前成员。

      <%= supermarket.name %><br />
      <%= supermarket.address %>
      

      我担心很多这些渲染的性能,但只要留意日志和时间,我认为渲染的时间与在原始视图中手动执行的时间大致相同。

      【讨论】:

      • 问题是 _supermarket.html.erb 属于超市模型和我试图将其渲染到的页面,另一个(supermarketchains),因此它们位于不同的文件夹下。我尝试了您的建议,但出现错误,Rails 告诉我找不到“supermarketchains/_supermarket.html.erb”,这很自然,因为该文件位于超市/_supermarket.html.erb 中。不过,将代码移入控制器是个好主意。
      猜你喜欢
      • 2016-02-03
      • 1970-01-01
      • 2017-08-10
      • 1970-01-01
      • 2012-12-31
      • 1970-01-01
      • 1970-01-01
      • 2012-12-23
      • 2013-06-24
      相关资源
      最近更新 更多