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.
精彩评论