Rails 3 - HAML块传递到原始上下文而不是部分呈现的部分

时间:2011-12-13 16:11:17

标签: ruby-on-rails ruby view haml partial

我有一个部分呈现我想在各种页面上重用的表。使用它的一些视图需要插入额外的列,因此我创建了辅助方法,用于添加和检索新的列标题以及用于根据当前行的数据生成< 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,因为我最后需要使用的代码将会复杂得多。任何见解都将不胜感激。

1 个答案:

答案 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