【问题标题】:Rails 3 - HAML Block Passed to Partial Rendered in Original Context instead of PartialRails 3 - 传递给在原始上下文中渲染的部分而不是部分的 HAML 块
【发布时间】:2012-01-19 12:16:28
【问题描述】:

我有一个部分呈现我想在不同页面上重复使用的表格。一些使用它的视图需要插入额外的列,因此我创建了用于添加和检索新列标题的辅助方法以及用于根据当前行的数据生成

的代码。

助手看起来像这样:

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

partial 在渲染表格之前使用帮助器指定列详细信息:

- 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 列时会使用部分中的 task 变量,但由于某种原因,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 块,因为我最终需要使用的代码会更多复杂的。任何见解将不胜感激。

【问题讨论】:

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


    【解决方案1】:

    HAML 会立即呈现对 table_column 的调用,而不是简单地将块添加到 @@tables。我相信它这样做是因为当您从部分调用块时,它会在您定义块的视图的上下文中呈现,而不是部分本身。更好的方法可能是根据您传递给它的本地人有条件地添加部分列:

    - 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 的本地名称被传递到部分并设置为 true 时才会呈现 ID 列,并且将始终呈现 Name、Start 和 End 列。然后你会调用部分喜欢:

    render "table" # Only renders the Name, Start & End columns
    

    render "table", :id => true # Renders the ID, Name, Start, & End columns
    

    【讨论】:

    • 如果我事先知道所有可能的列标题,您的建议会奏效。但是,这部分是我组织中其他部门创建的不同应用程序使用的 rails 引擎(gem)的一部分。此外,我在此处提供的代码是对实际代码的简化,并且将每个可能的列都编码在同一个部分中会使该部分变得非常臃肿。
    • 我发现初始视图如何立即为 ID 列呈现 HAML 令人困惑,因为该视图甚至没有 任务多变的。 task 变量在渲染部分之前不会被设置。知道它是如何工作的吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-13
    • 1970-01-01
    • 2012-10-16
    • 2016-03-02
    • 1970-01-01
    • 2011-03-22
    • 2023-03-11
    相关资源
    最近更新 更多