如何从Ruby块中的多个语句中产生结果?

时间:2012-01-24 19:54:32

标签: ruby-on-rails ruby

我有一对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) 。有人能帮我弄清楚这里的魔术是什么吗?

1 个答案:

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