简体   繁体   English

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

[英]Mysterious Ruby Block behavior: &block vs. {block.call}

When writing a helper for printing javascript that can be used from both other helpers and views, I stumbled upon the following problem: 当编写一个帮助打印可以从其他助手和视图中使用的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

This helper should be called with javascript { "alert('hurray'); } . 应该使用javascript { "alert('hurray'); }来调用此帮助程序。

In the first alternative - which I expected to work - the Rails javascript_tag helper renders an empty <script type="text/javascript"> //<![CDATA[ //]]> </script> tag. 在第一个替代方案 - 我期望工作 - Rails javascript_tag帮助器呈现一个空的<script type="text/javascript"> //<![CDATA[ //]]> </script>标记。

The second alternative, however, works as expected. 然而,第二种选择按预期工作。

What's going on there? 那里发生了什么? How can that be different? 怎么会有所不同?

You say you are doing this on your views, right? 你说你在观点上这样做,对吗?

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

But for content_tag(&block) to work, you should call javascript the way content_tag is intended to be used in views, which is: 但是content_tag(&block)工作,你应该以在视图中使用content_tag的方式调用javascript ,这是:

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

content_tag 's behavior is different depending on where it's called from, see the function block_called_from_erb? content_tag的行为根据调用的位置而有所不同,请参阅函数block_called_from_erb? in the source code. 在源代码中。 In the first case this function returns true because the block does come from an erb (and then it's concat ed, you don't want that!), in the second returns false (you re-created the block from scratch) and content_tag simply returns the string content, which is what you want. 在第一种情况下,这个函数返回true因为块确实来自erb(然后它是concat ,你不需要!),在第二种情况下返回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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM