神秘的Ruby Block行为:& block vs. {block.call}

时间:2010-12-20 13:53:03

标签: ruby-on-rails ruby block

当编写一个帮助打印可以从其他助手和视图中使用的javascript时,我偶然发现了以下问题:

def javascript(print_tag = false, &block)
  content_for(:javascript) do
    if print_tag
      javascript_tag(&block)          # does not work
      javascript_tag { block.call }   # does work 
    else
      capture(&block)
    end
  end
end

应使用javascript { "alert('hurray'); }调用此助手。

在第一个替代方案中 - 我希望工作 - Rails javascript_tag helper呈现一个空的<script type="text/javascript"> //<![CDATA[ //]]> </script>标记。

然而,第二种选择按预期工作。

那里发生了什么?怎么会有所不同?

1 个答案:

答案 0 :(得分:4)

你说你的观点是这样做的,对吗?

<%= javascript { "alert('hurray');" } %>

但要让content_tag(&block)生效,您应该按照javascript的方式调用content_tag,以便在视图中使用:

<% javascript do %>
  alert('hurray');
<% end %>

content_tag的行为因其调用位置而异,请参阅源代码中的函数block_called_from_erb?。在第一种情况下,此函数返回true,因为块确实来自erb(然后它是concat ed,你不需要!),在第二种情况下返回false(你从头开始重新创建了块)而content_tag只返回字符串内容,这就是你想要的。

# ./action_view/helpers/javascript_helper.rb
tag = content_tag(:script, javascript_cdata_section(content), html_options.merge(:type => Mime::JS))
if block_called_from_erb?(block)
  concat(tag)
else
  tag
end