Частичный рендеринг в Ruby on rails: коллекция умножает элементы

Я хочу отобразить список элементов на странице в Ruby-on-Rails. я использую частичные

в моем файле index.html.erb у меня есть:

<%= @lista = News.find(:all, :order => Document::COL_DATE + ' DESC, id DESC')
    render :partial => "newsitem",
           :layout => "list_news",
           :spacer_template => "spacer",
           :collection => @lista
%>

в _list_news.html.erb у меня есть:

<div class="news">
  <%= yield %>
</div>

в _spacer.html.erb у меня <hr/>

в _newsitem.html.erb у меня есть

<%= newsitem_counter + 1 %>
<!-- Code to print details for one item -->

Проблема в том, что он печатает список несколько раз:

Если в списке 3 элемента, он показывает их 3 раза: 1,2,3,1,2,3,1,2,3.
Если в списке 7 элементов, эти элементы печатаются 7 раз.

Что не так в моем коде?


person True Soft    schedule 05.02.2010    source источник
comment
вставьте журнал в свой код просмотра, чтобы увидеть, что вызывается повторно.   -  person klochner    schedule 05.02.2010


Ответы (2)


Параметр :layout обычно используется с :action или одиночным :partial, но не с :collection. Проблема: yield вызывается для каждого элемента в списке.

Вам придется просмотреть исходники, чтобы понять, почему :layout и :collection ведут себя таким образом; но достаточно сказать, что ваш код, вероятно, следует просто переписать, чтобы он не полагался на совместную работу :layout и :collection.

Вот один из способов сделать это, предполагая, что повторное использование этого кода в других представлениях имеет высокий приоритет. Если вы не используете большое количество кэширования, рендеринг каждой части будет довольно медленным, особенно если в вашей новостной_ленте много элементов, поэтому я объединил их в один.

controller/news_controller.rb

class NewsController < ApplicationController
   def index
     @news_feed = News.find(:all, 
                            :order => Document::COL_DATE + ' DESC, id DESC')
   end
end

views/news/index.html.erb

<%= render :partial => "news_feed",
       :locals => { :news_feed => @news_feed} %>

views/news/_news_feed.html.erb

<ul class="news">
  <% news_feed.each_with_index do |news_item, news_item_counter| %>
     <li>
       <%= newsitem_counter + 1 %>
      <%# Code to print details for one item %>
     </li>
  <% end %>
</ul>

Если рендеринг целой кучи партиалов вас устраивает с точки зрения времени выполнения, вам может показаться, что эта реализация views/news/_news_feed.html.erb лучше:

<div class="news">
  <%= render :partial => 'news_item', :collection => news_feed, :spacer_template => "horizontal_break" %> 
</div>

views/news/_news_item.html.erb

<%= newsitem_counter + 1 %>
<%# Code to print details for one item %>

views/news/_horizontal_break.html.erb

<hr />

Таким образом, вместо рендеринга :layout вы рендерите один большой партиал, обертывающий коллекцию.

person Tim Snowhite    schedule 05.02.2010
comment
Это то, что я писал, когда увидел, что вы публикуете ответ, и ваш ответ более подробный, чем мой. +1. - person Austin Fitzpatrick; 05.02.2010
comment
Спасибо за такой подробный ответ. Я использовал первый метод. - person True Soft; 06.02.2010

Это известная проблема в Rails 2.3.8 и Rails 3! https://rails.lighthouseapp.com/projects/8994/tickets/2279-render-layout-with-block-and-multiple-yields

person Aditya Sanghi    schedule 27.06.2010