我有一个部分呈现我想在各种页面上重用的表。使用它的一些视图需要插入额外的列,因此我创建了辅助方法,用于添加和检索新的列标题以及用于根据当前行的数据生成< TD>的代码。
助手看起来像这样:
def table_column table_name, column_name, &block
raise "block required" unless block_given?
@@tables ||= {}
table = @@tables[table_name]
if table.nil?
@@tables[table_name] = table = []
end
index = table.size
table[index] = [column_name, block]
end
def table_cells table_name
table = @@tables[table_name] || []
table.map { |column| column[0] }
end
def table_headers table_name
table = @@tables[table_name] || []
table.map { |column| column[1] }
end
部分使用帮助程序在呈现表之前指定列详细信息:
- table_column "tasks", "Name" do |task|
%td= task.name
- table_column "tasks", "Start" do |task|
%td= task.start_time.strftime(time_format)
- table_column "tasks", "End" do |task|
%td= task.end_time.strftime(time_format)
%table
%thead
%tr
- table_headers("tasks").each do |header|
%th= header
%tbody
- @tasks.each do |task|
%tr
- table_cells("tasks").each do |cell|
- cell.call(task)
这很好用。然后我有一个视图,在渲染部分之前添加一列:
- table_column "tasks", "ID" do |task|
%td=task.id
= render "table"
部分的任务变量在渲染ID列时会被使用,但由于某种原因,ID单元格会在上面表格中呈现!生成的HTML与此类似:
<td>10001</td>
<td>10002</td>
<td>10003</td>
<table>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Start</th>
<th>End</th>
</tr>
</thead>
<tbody>
<tr>
<td>Steal underpants</td>
<td>Feb.12, 2012</td>
<td>Jun.07, 2012</td>
</tr>
<tr>
<td>???</td>
<td>Jun.08, 2012</td>
<td>Nov.13, 2012</td>
</tr>
<tr>
<td>Profit!</td>
<td>Nov.14, 2012</td>
<td>Jan.23, 2013</td>
</tr>
</tbody>
</table>
好像HAML渲染器正在记住传递给 table_column 的块的原始上下文,但仅限于从局部外部传递。作为测试,我将ID列代码移动到局部,并且它适用于该情况。我也试过,将字符串而不是块传递给 table_column (工作),但我真的更喜欢传递一块HAML,因为我最后需要使用的代码将会复杂得多。任何见解都将不胜感激。
答案 0 :(得分:0)
HAML立即呈现对table_column的调用,而不是简单地将块添加到@@ tables。我相信它是这样做的,因为当您从partial调用块时,它将在您定义块的视图的上下文中呈现,而不是部分本身。更好的方法可能是有条件地使用部分添加列,具体取决于您传递给它的本地:
- if defined?(id) && id
- table_column "tasks", "ID" do |task|
%td=task.id
- table_column "tasks", "Name" do |task|
%td= task.name
- table_column "tasks", "Start" do |task|
%td= task.start_time.strftime(time_format)
- table_column "tasks", "End" do |task|
%td= task.end_time.strftime(time_format)
%table
%thead
%tr
- table_headers("tasks").each do |header|
%th= header
%tbody
- @tasks.each do |task|
%tr
- table_cells("tasks").each do |cell|
- cell.call(task)
在这种情况下,仅当将名为id
的本地传递给partial并将其设置为true并且始终呈现Name,Start和End列时,才会呈现ID列。然后你会调用部分:
render "table" # Only renders the Name, Start & End columns
或
render "table", :id => true # Renders the ID, Name, Start, & End columns