我目前正在为一个gem工作一个ERB View类。有了这个类,我想为ERB模板提供一些辅助方法
关于像h(string)
这样的基本助手是可以的。我发现erbh
gem帮助我了解更多情境的工作原理
但现在我正在尝试创建一个像Rails或Sinatra中的content_for
方法。
我第一次使用简单的Proc
来捕获视图块,然后只需调用call
方法来打印它。它在开始时工作得很好。
但在完成视图后,我看到有线认为,有些内容被多次打印
所以我看看Sinatra ContentFor helper来了解他们是如何做到的,我复制了这个助手的一些方法。我没有错误,但是块返回总是空的......我真的不知道为什么。
我对ERB的了解不足以了解ERB缓冲的工作原理。
这是一个解释我的代码状态的要点。我从我的库中提取了代码并对其进行了简化。
我只想让content_for
方法与Rails和Sinatra一样工作。
谢谢!
答案 0 :(得分:0)
阅读完这篇blog article后,我终于找到了为什么它不起作用。我不知道我是以最好的方式和更干净的方式做到的,但它确实有效。
因此该错误主要来自ERB
启动。通过使用属性而不是局部变量eoutvar
,它现在可以正常工作。
erb = ERB.new(str, nil, "<>", "@_erbout")
我还更改了capture
帮助程序使用的content_for
方法。
现在看起来像这样(gist)
def content_for(key, content = nil, &block)
block ||= proc { |*| content }
content_blocks[key.to_sym] << capture_later(&block)
end
def content_for?(key)
content_blocks[key.to_sym].any?
end
def yield_content(key, default = nil)
return default if content_blocks[key.to_sym].empty?
content_blocks[key.to_sym].map { |b| capture(&b) }.join
end
def capture(&block)
@capture = nil
@_erbout, _buf_was = '', @_erbout
result = yield
@_erbout = _buf_was
result.strip.empty? && @capture ? @capture : result
end
def capture_later(&block)
proc { |*| @capture = capture(&block) }
end