Is there a way to use a Ruby loop inside of HAML&#

2019-01-19 12:08发布

问题:

Inside of HAML, can we have a loop inside the :javascript region?

This will work:

- 10.upto(20) do |i|
  :javascript
    document.getElementById('aDiv').innerHTML += '#{i}';

and this will not:

:javascript
  - 10.upto(20) do |i|
    document.getElementById('aDiv').innerHTML += '#{i}';

can the code above also be made to work as well?

回答1:

this one works

%script
  - 10.upto(20) do |i|
    document.getElementById('aDiv').innerHTML += '#{i}';


回答2:

%html
  %head
    :javascript
      var foo = [];
      #{
        limit = rand(4)+3
        array = (0..limit).to_a
        array.map{ |i| "foo[#{i}] = #{rand(12)};" }.join ' '
      }
      console.log(foo.length);
    %body

Running the above code gives this output:

<html>
  <head>
    <script type='text/javascript'>
      //<![CDATA[
        var foo = [];
        foo[0] = 2; foo[1] = 0; foo[2] = 11; foo[3] = 8; foo[4] = 0; foo[5] = 1;
      //]]>
    </script>
    <body></body>
  </head>
</html>

As you can see, the big #{...} block (which may span multiple lines) runs arbitrary Ruby code. The result of the last expression (in this case the map{...}.join) is converted to a string and placed in the output.

Edit for Radek: If you want to declare a variable inside you Haml template, inside your JavaScript filter (which seems like an odd desire), then you need to be sure that the result of the block to_s doesn't produce unwanted output:

This Haml...

%p
  :javascript
    var foo = 12;
    #{x = 42}
    var bar = #{x};

...produces this HTML:

<p>
  <script type='text/javascript'>
    //<![CDATA[
      var foo = 12;
      42
      var bar = 42;
    //]]>
  </script>
</p>

Whereas this Haml...

%p
  :javascript
    var foo = 12;
    #{x = 42; ""}
    var bar = #{x};

...produces this HTML...

<p>
  <script type='text/javascript'>
    //<![CDATA[
      var foo = 12;

      var bar = 42;
    //]]>
  </script>
</p>

But before you do this, ask yourself: why am I creating complex Ruby variables in my view?
Shouldn't this variable have been declared by my controller?



回答3:

Just wanted to add that the following gets you the type and CDATA, but without the funky behaviour of :javascript (I just had to implement something like this).

%script{ :type => 'text/javascript' }
  \//<![CDATA[
  - (10..20) do |i|
    document.getElementById('aDiv').innerHTML += '#{i}';
  \//]]>