Ruby ERB - 创建content_for方法

时间:2016-08-20 23:36:54

标签: ruby erb

我目前正在为一个gem工作一个ERB View类。有了这个类,我想为ERB模板提供一些辅助方法 关于像h(string)这样的基本助手是可以的。我发现erbh gem帮助我了解更多情境的工作原理 但现在我正在尝试创建一个像Rails或Sinatra中的content_for方法。

我第一次使用简单的Proc来捕获视图块,然后只需调用call方法来打印它。它在开始时工作得很好。
但在完成视图后,我看到有线认为,有些内容被多次打印 所以我看看Sinatra ContentFor helper来了解他们是如何做到的,我复制了这个助手的一些方法。我没有错误,但是块返回总是空的......我真的不知道为什么。

我对ERB的了解不足以了解ERB缓冲的工作原理。

代码

这是一个解释我的代码状态的要点。我从我的库中提取了代码并对其进行了简化。

https://gist.github.com/nicolas-brousse/ac7f5454a1a45bae30c52dae826d587f/66cf76c97c35a02fc6bf4a3bc13d8d3b587356de

我想要什么?

我只想让content_for方法与Rails和Sinatra一样工作。

谢谢!

1 个答案:

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