使用ERB在.yml.erb中嵌入子模板时内容丢失问题求助
问题原因与解决方案
错误根源
你当前的写法中,子模板的ERB实例默认会直接将渲染内容输出到$stdout,而父模板里的<%=试图接收返回值再输出,这会导致输出顺序彻底混乱——子模板的内容会先于父模板的前置内容被打印,缓冲区的处理逻辑会直接覆盖掉父模板嵌入代码上方的内容,哪怕去掉gsub处理,这个核心冲突依然存在。
修复方案
方案一:复用父模板的输出缓冲区(推荐)
修改父模板中的嵌入代码,指定子模板ERB使用父模板的输出缓冲区,避免直接输出到标准输出:
<% ERB.new(File.read('child.yml.erb'), nil, ' ', '@output_buffer').result(binding) %>
- 第四个参数
'@output_buffer':让子模板的渲染内容直接写入父模板正在使用的输出缓冲区,确保内容嵌入位置正确,不会打乱整体输出顺序。 - 缩进处理:如果需要给子模板内容添加8空格缩进,保留你的
gsub逻辑即可:<% ERB.new(File.read('child.yml.erb').gsub(/^/, ' ' * 8), nil, ' ', '@output_buffer').result(binding) %>
方案二:捕获子模板输出为字符串(纯Ruby环境适用)
如果你的环境不支持@output_buffer(非Rails等框架场景),可以用StringIO手动捕获子模板的输出,再输出到父模板:
<%= begin output = StringIO.new original_stdout = $stdout $stdout = output ERB.new(File.read('child.yml.erb')).result(binding) $stdout = original_stdout output.string.gsub(/^/, ' ' * 8) end %>
验证示例
假设父模板parent.yml.erb内容:
env_a: key1: value1 <% # 嵌入子模板 %> <% ERB.new(File.read('child.yml.erb').gsub(/^/, ' ' * 8), nil, ' ', '@output_buffer').result(binding) %> env_d: key4: value4
子模板child.yml.erb内容:
env_b: key2: value2 env_c: key3: value3
渲染后会得到正确的嵌套结果:
env_a: key1: value1 env_b: key2: value2 env_c: key3: value3 env_d: key4: value4
内容的提问来源于stack exchange,提问作者Andrew Lim
相关产品推荐
相关产品推荐

