如何使用两个或多个嵌套子项创建自己的块助手?

时间:2011-08-27 23:19:18

标签: ruby-on-rails-3 ruby-on-rails-3.1

我想在我的观点中嵌套这样的东西:

<%= helper_a do |ha| %>
  Content for a
  <%= ha.helper_b do |hb| %>
    Content for b
    <%= hb.helper_c do |hc| %>
      Content for c
      ... and so on ...
    <% end %>
  <% end %>
<% end %>

举例来说:

<tag_a>
  Content for a
  <tag_b class="child_of_tag_a">
    Content for b
    <tag_c class="nested_child_of_tag_a child_of_tag_b">
      Content for c
    </tag_c>
  </tag_b>
</tag_a>

这意味着,每个级别都可以访问上述级别的某些信息(这就是为什么它们是嵌套的而不是完全自治的方法)

我知道如何创建一个简单的帮助器:

def helper_a(&block)
  content = capture(&block)
  content_tag :tag_a, content
end

而且我知道我可以将我的论点传递给capture以在视图中使用它们,所以像这样的东西可以实现我的示例的|ha|

def helper_a(&block)
  content = capture(OBJECT_HERE, &block)
  content_tag :tag_a, content
end

但是我在哪里定义这个OBJECT_HERE,特别是它的类,以及如何嵌套多个级别捕获每个块?

1 个答案:

答案 0 :(得分:1)

我想出了几个解决方案,但我还远不是Rails模板系统的专家。

第一个是使用实例变量:

def helper_a(&block)
  with_context(:tag_a) do
    content = capture(&block)
    content_tag :tag_a, content
  end
end

def helper_b(&block)
  with_context(:tag_b) do
    content = capture(&block)
    content_tag :tag_b, content
  end
end

def helper_c(&block)
  with_context(:tag_c) do
    content = capture(&block)
    content_tag :tag_c, content
  end
end

def with_context(name)
  @context ||= []
  @context.push(name)
  content = yield
  @context.pop
  content
end

以这种方式使用:

<%= helper_a do %>
  Content for a
  <%= helper_b do %>
    Content for b
    <%= helper_c do %>
      Content for c
      ... and so on ...
    <% end %>
  <% end %>
<% end %>

另一个解决方案,它在每个步骤传递上下文:

def helper_a(context = [], &block)
  context = capture(context.push(:tag_a), &block)
  content_tag(:tag_a, content)
end

def helper_b(context = [], &block)
  context = capture(context.push(:tag_b), &block)
  content_tag(:tag_b, content)
end

def helper_c(context = [], &block)
  context = capture(context.push(:tag_c), &block)
  content_tag(:tag_c, content)
end

以这种方式使用:

<%= helper_a do |context| %>
  Content for a
  <%= helper_b(context) do |context| %>
    Content for b
    <%= helper_c(context) do |context| %>
      Content for c
      ... and so on ...
    <% end %>
  <% end %>
<% end %>

但是我真的建议不要使用这些解决方案,如果你所做的只是CSS样式和/或Javascript操作。这真的使助手变得复杂,可能会引入错误等。

希望这有帮助。