Mysterious behavior of the Ruby block: & block vs. {block.call}

When writing a javascript print helper that can be used from both other helpers and views, I came across the following problem:

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 using javascript { "alert('hurray'); } .

In the first version, which I expected to work, the Rails javascript_tag helper displays an empty tag <script type="text/javascript"> //<![CDATA[ //]]> </script> .

The second option, however, works as expected.

What is happening there? How could it be otherwise?

+4
source share
1 answer

You say you do it on your own views, right?

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

But for content_tag(&block) to work, you must call javascript content_tag method that you intend to use in views:

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

content_tag behavior differs depending on where it is called from, see block_called_from_erb? function block_called_from_erb? in the source code. In the first case, this function returns true , because the block really comes from erb (and then it concat ed, you do not want it!), In the second case it returns false (you re-created the block from scratch), and the content_tag just returns the contents of the string, which you need.

 # ./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 
+4
source

Source: https://habr.com/ru/post/1332764/


All Articles