无法在 Rails 帮助程序中捕获块的输出

Cannot capture output of block in Rails helper

我 运行 遇到了自定义 Rails FormBuilder 的问题,从昨天晚上开始我就发疯了。基本上我想对我的构建器方法之一有一个可选块,这样我就可以在我的主要 content_tag:

中显示其他内容
def form_field(method, &block)
  content_tag(:div, class: 'field') do
    concat label(method, "Label #{method}")
    concat text_field(method)
    capture(&block) if block_given?
  end
end

当我在我的 Slim 模板之一中调用该方法时,如下所示:

= f.form_field :email do
  small.help-text
    | Your email will never be public.

它在 content_tag:

的实际输出之上插入块(此处:<small> 中的帮助文本)
<small class="help-text">Your email will never be public.</small>
<div class="field">
    <label for="user_email">Label email</label>
    <input type="text" value="" name="user[email]" id="user_email">
</div>

我尝试了其他几种变体,但似乎我永远无法捕获 block 的输出。任何想法 - 也许更有趣:对这种行为的解释?我阅读了几篇有关该主题的文章,还查看了 Rails 源代码,但无法真正弄清楚为什么会这样。

所以,经过更多的挖掘,发现问题出在 FormBuilder 以及它本身如何处理输出缓冲区。查看 ActionView FormHelpers 的源代码,提示在 @template 上调用捕获,如下所示:

def form_field(method, &block)
  content = @template.capture(&block) if block_given?
  content_tag(:div, class: 'field') do
    concat label(method, "Label #{method}")
    concat text_field(method)
    concat content if content.present?
  end
end

正如@Kitto 所说,:capture:concat 和更多其他帮助程序都实现了@template。

在我的习俗中 FormBuilder,我有这个:

module CustomFormBuilder < ActionView::Helpers::FormBuilder
  delegate :content_tag, :concat, to: :@template

  [ ... your code ... ]
end