【问题标题】:Cannot capture output of block in Rails helper无法在 Rails 帮助程序中捕获块的输出
【发布时间】:2015-05-04 20:03:31
【问题描述】:

我在使用自定义 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.

它将块(此处:<small> 中的帮助文本)插入到 content_tag 的实际输出上方:

<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 源代码,但无法真正弄清楚它为什么会这样。

【问题讨论】:

    标签: ruby-on-rails ruby slim-lang


    【解决方案1】:

    正如@Kitto 所说,:capture:concat 和更多其他帮助器已实现到@template。

    在我的习惯FormBuilder,我有这个:

    module CustomFormBuilder < ActionView::Helpers::FormBuilder
      delegate :content_tag, :concat, to: :@template
    
      [ ... your code ... ]
    end
    

    【讨论】:

    • 这应该在某种最佳实践指南中。向你和@Kitto 竖起大拇指!
    【解决方案2】:

    所以,经过更多的挖掘,问题在于 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
    

    【讨论】:

      猜你喜欢
      • 2011-03-29
      • 2013-06-23
      • 2011-08-15
      • 2023-03-12
      • 1970-01-01
      • 1970-01-01
      • 2018-04-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多