开发者

How to create own block helper with two or more nested children?

I'd like to to something nested like that in my views:

<%= 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 %>

To get for example this:

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

This means, each level has access to some information of the level above (th开发者_如何学运维at's why they are nested and not completely autonomous methods)

I know how to create a simple helper:

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

And I know I can pass my arguments to the capture to use them in the view, so something like this to get live up the |ha| of my example

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

But where do I define this OBJECT_HERE, especially the class for it, and how can this go on nested with multiple levels capturing each block?


I came up with a couple solutions, but I'm far from being an expert in the Rails templating system.

The first one is using an instance variable :

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

which is used this way :

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

And the other solution, which passes the context at each step :

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

which is used this way :

<%= 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 %>

But I'd really advise against using either of these solutions if all you're doing is CSS styling and/or Javascript manipulation. It really complicates the helpers, is likely to introduce bugs, etc.

Hope this helps.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜