开发者

RoR remember state in partial renderer

how can I remember some state within a partial renderer?

Problem at hand: my partial _testitem.html.erb renders table rows of a collection of testitems. A Testitem has an id and a sortkey and the partial is called with

<%= render :partial => "testitem", :collection => @testbox.testitems.sort_by{|x| [x.sortkey, x.id]} %>

i.e. all testitems are sorted by the sortkey and then by their id. Now I'd like to display a table column that shows the current sortkey and I thought it would be neat to use

<td rowspan="<%= Testitem.count_by_sql "SELECT count(*) from testitems where sortkey=#{testitem.sortkey}" %>"><%=h开发者_高级运维 testitem.sortkey %></td>

which of course breaks the table, as every <td> get's the rowspan. The expected result would look somewhat like

Group   |   Id  |    Description |
----------------------------------
   1    |    1  |    ...         |
        --------------------------
        |    2  |    ...         |
        --------------------------
        |    16 |    ...         |
----------------------------------
   2    |    3  |    ...         |
----------------------------------
   3    |    4  |    ...         |
        |   10  |    ...         |
        |   11  |    ...         |
 ---------------------------------

Is there a way to "remember" (within _testitem.html.erb) the fact that I added the <td rowspan=""> already for a given sortkey?

Thanks for helping me out.


First, if you use all the testitems of a testbox anyway, you dont need that extra count queries.

What you want to do, is to draw the first item partial with the td of the group, and then draw the rest of the items regularly..

in the controller:

@testitems_by_keys = @testbox.testitems.group_by(&:sortkey)

in you view:

<% @testitems_by_keys.each do |group, items| %>
  <%= render :partial => "item", :locals => { :object => items.shift, :group => group, :size => items.size+1 } %>
  <%= render items %>
<% end %>

in _item:

<tr>
<% if local_assigns[:group].present?  %>
  <td rowspan="<%= size %>"><%= group %></td>
<% end %>
rest of the partial....
</tr>

note: just wrote it here.. may or may not contain syntax errors.


In your model you could do something like:

class TestBox  
  named_scope :sorted_items, :sort_by => :sort_key, :id

  def grouped_items
    sorted_items.group_by(&:sort_key)
  end
end

and in your view you can do:

<% @test_box.grouped_items.each do |sort_key, items| %>
  <td rowspan="<% items.length %>"><%= render :partial => 'test_item', :collection => items %></td>
<% end %>

and in the test_item partial:

<%= h item.sort_key %>

I am not completely sure this will give you exactly what you are looking to do, but it will get you a good start in the right direction.


One solution you could try... first, get a hash of all the rowspans necessary for each sortkey.

@rowspans = TestItem.count(:group => sortkey)

Then, in the partial, as you're rendering each row, set an instance variable to check if you're rendering rows with the current sortkey...

<% if testitem.sortkey != @current_sort_key %>
  <% @current_sort_key = testitem.sortkey %>
  <td rowspan="<%= @rowspans[@current_sort_key] -%>">
    <%= testitem.sortkey %>
  </td>
<% end %>
... render the rest of row ...

Depending on how clean you like your views to be, this might be better written inside of a helper, rather than in the view itself.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜