我有一对Rails助手,其中一个是接受一个块而另一个只是渲染一个按钮。以下是帮助程序定义的简化版本:
def nav_wrapper(nav_at, id, css_class, &block)
"<ul class="complicated">\n #{yield} \n</ul>".html_safe
end
def nav_btn(nav_at, caption, id = caption.downcase.dasherize)
"Nav button codes goes here".html_safe
end
我正在尝试设置这样的东西,我可以这样做:
<%= nav_wrapper(@nav_at, "Top Nav", "class") do %>
<%= nav_btn(@nav_at, "Foo", "id") %>
<%= nav_btn(@nav_at, "Bar", "id") %>
<%= nav_wrapper(@nav_at, "Sub Nav", "class") do %>
<%= nav_btn(@nav_at, "SubFoo", "id") %>
<%= nav_btn(@nav_at, "SubBar", "id") %>
<% end %>
<% end %>
但是,yield
方法中的nav_wrapper
只会获取每个块的最后一个语句。所以在这个例子中,我得到了Top Nav包装器,跳过了Foo和Bar,我得到了Sub Nav包装器(是外部nav_wrapper
块中的最后一个语句),SubFoo被跳过了,我得到了SubBar(正在内部nav_wrapper
块中的最后一个语句。
我知道这种行为的原因是代码块隐式返回最后一个评估值,但我知道有很多模板助手可以呈现所有插页式行(例如form_for
) 。有人能帮我弄清楚这里的魔术是什么吗?
答案 0 :(得分:3)
编译ERB模板时,会将其转换为将字符串添加到缓冲区的代码。 (查看ERB的源代码以了解我的意思。)来自Action View的方法(如form_for
)执行块,然后检索ERB缓冲区中的文本。
打开lib/ruby/1.9.1/gems/1.9.1
文件夹,查找actionpack。打开您拥有的任何Action Pack版本,然后转到lib/action_view/helpers/capture_helper.rb
。那里有一个名为capture
的方法,form_for
使用该方法执行一个块并检索ERB生成的文本。
如果您正在编写Rails帮助程序,那么您的代码可能会capture
。如果没有,请尝试include ActionView::Helpers::CaptureHelper
。