简体   繁体   English

Rails helper_method 可以像在相应视图中调用它一样使用 yield 吗?

[英]Can a Rails helper_method use yield as if it was invoked in the corresponding view?

I have the following accordion generator which works fine when included directly in the view:我有以下手风琴生成器,当直接包含在视图中时可以正常工作:

<%
def collapser(name)
  fad = {
    class: 'collapsed',
    data: {toggle: 'collapse', parent: '#accordion_id'},
    href: "##{name}",
    aria: {expanded: 'true', controls: name}
  }
  tag.div(class: 'panel panel-default') do
    tag.div(class: 'panel-heading', role: 'tab') do
      tag.p(class: 'panel-title') do
        tag.a(fad) do
          tag.span do
            t("section.#{name}.title")
          end
        end
      end
    end +
    tag.div(id: name, class: 'panel-collapse collapse', role: 'tabpanel', style: 'height: 0px;', aria: {labelledby: name}, data: {parent: '#accordion_id'}) do
      tag.div(class: 'panel-body') do
        tag.div(class: 'uncode_text_column') do
          yield
        end
      end
    end
  end
end
%>

<%= tag.div(id: 'accordion_id', class: 'panel-group', role: 'tablist', aria: {multiselectable: 'true'}) do %>    
    <%= collapser('example') do %>
      <%= tag.p t('section.example.nub.row1') %>
    <% end %>
<% end %>

Now I wanted to move toward a more clean implementation by:现在我想通过以下方式实现更干净的实现:

  • moving collapser to the matching controllercollapser器移动到匹配的 controller
  • make a generic_collapser(name, parent) so制作一个generic_collapser(name, parent)所以
    • it's more broadly accessible in other part of the code base在代码库的其他部分可以更广泛地访问它
    • this specific collapser can be implemented as a call to generic_collapeser(name, 'accordion_id')这个特定的折叠器可以通过调用generic_collapeser(name, 'accordion_id')来实现

But I'm stuck with the first step, as I'm not able to handle the context change properly.但是我坚持第一步,因为我无法正确处理上下文更改。 First, tag is no longer accessible, but simply assigning tag = view_context.tag seems to do the job.首先, tag不再可访问,但简单地分配tag = view_context.tag似乎可以完成这项工作。 However, I didn't found a way to transpose yield statement.但是,我没有找到转置yield语句的方法。 I tried the following我尝试了以下

  • keep tag.div(class: 'uncode_text_column') { yield }保持tag.div(class: 'uncode_text_column') { yield }
  • use tag.div(class: 'uncode_text_column') { view_contex{yield} }使用tag.div(class: 'uncode_text_column') { view_contex{yield} }
  • use tag.div(class: 'uncode_text_column') { view_contex(&block) } , together with def collapser(name, &block)使用tag.div(class: 'uncode_text_column') { view_contex(&block) }def collapser(name, &block)

But none gave the expected result.但没有人给出预期的结果。

Hints toward good resources to better understand view_context , yield and block management would also be welcome, especially tutorial with exercises.也欢迎提供更好的资源以更好地理解view_contextyield和块管理,尤其是带有练习的教程。

What's this &block in Ruby? Ruby 中的 &block 是什么? And how does it get passed in a method here? 它是如何在这里通过方法传递的?

So, the key feature to use here is the capture method.因此,这里使用的关键特性是capture方法。 Here is how it was used to solve this issue as it was specified in the question:这是问题中指定的用于解决此问题的方法:

<% # in the view %>
<% content[:section_1] = capture do %>
  <%= tag.ul do %>
    <%= tag.li item 1 %>
    <%= tag.li item 2 %>
    <%= tag.li item 3 %>
  <% end %>
<% end %>

<% content[:section_2] = capture do %>
  <%= tag.p 'some paragraphe %>
<% end %>

<% bib = "accordion_#{SecureRandom.hex}" %>
<% title = ->(name){t("section.#{name}.title")} %>
<%= tag.div(id: bib, class: 'panel-group', role: 'tablist', aria: {multiselectable: 'true'}) do %>
  <% content.each do |key, nub| %>
    <%= collapser(key, title[key], nub, bib) %>
  <% end %>
<% end %>

And on the other side而在另一边

  # Within helpers
  # Returns a collapsable html div usable as an accordion item
  # Params:
  # +name+:: identifier for this div
  # +title+:: text used as title of the collapsable div
  # +content+:: text used as contont of the collapsable div
  # +parent+:: identifier of the parent accordion div
  def collapser(name, title, content, parent)
    link_fad = {
      class: 'collapsed',
      data: {toggle: 'collapse', parent: "##{parent}"},
      href: "##{name}",
      aria: {expanded: 'true', controls: name}
    }
    content_fad = {
      id: name,
      class: 'panel-collapse collapse',
      role: 'tabpanel',
      style: 'height: 0px;',
      aria: {labelledby: name},
      data: {parent: "##{parent}"},
    }
    tag.div(class: 'panel panel-default') do
      tag.div(class: 'panel-heading', role: 'tab') do
        tag.p(class: 'panel-title') do
          tag.a(link_fad) do
            tag.h2 do
              title
            end
          end
        end
      end + # note the plus here so we return a single string with the whole HTML
      tag.div(content_fad) do
        tag.div(class: 'panel-body') do
          tag.div(class: 'uncode_text_column' ) do
            content
          end
        end
      end
    end
  end

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM