12
  • how can I run ruby code inside javascript in haml?
  • if I use var = #{message} in my example I get undefined local variable or method message
  • when I move - message = 'it works' above :javascript everything works fine

I want to run iteration .each inside :javascript. See the last code sample for what I need in final javascript code. Where I need to loop few ruby variables (or one hash of hashes of hashes?) to get this. Data (='basics') can have few elemenets. It can have children with few elements etc.

SO this haml code

%html
  %head
    :javascript
      $(document).ready(function() {
        - message = 'it works'
            var = message

        });
%body
    - message2 = 'hi'
    = message2
    %div{:id =>"jstree"}

gives me this html code

<html>
  <head>
    <script type='text/javascript'>
      //<![CDATA[
        $(document).ready(function() {
            - message = 'hi'
            var = message

        });
      //]]>
    </script>
  </head>
  <body>
    hi
    <div id='jstree'></div>
  </body>
</html>

The final javascript code I want to produce using haml is the javascript variable

var data = [{
       data: "basics",
       attr: {},
        children: [
         {data: "login", attr: {run: "run"},
           children: [                   
           {data: "login", attr: {}}
          ]
         } ,
         {data: "Academic Year", attr: {run: "run"},
          children: [                   
           {data: "login", attr: {}},
           {data: "Academic Year", attr: {filter: "mini", SOF: "yes"}}
          ]

         }
        ]
      }];
Radek
  • 13,813
  • 52
  • 161
  • 255
  • This question is not easy to understand. You say you want to run `each`, but you don't show where or how. I'm not sure what setting the `message` variable before your script block has to do with your question. **What Ruby variables do you have, and what do you want as the output?** – Phrogz May 03 '11 at 02:58
  • 1
    Possible duplicate: [Is there a way to use a Ruby loop inside of Haml's JavaScript region?](http://stackoverflow.com/questions/2962119/is-there-a-way-to-use-a-ruby-loop-inside-of-hamls-javascript-region/5864657#5864657) – Phrogz May 03 '11 at 03:11
  • possible duplicate of [Injecting variable values into javascript and HAML in RoR](http://stackoverflow.com/questions/4708369/injecting-variable-values-into-javascript-and-haml-in-ror) – Ciro Santilli OurBigBook.com Jun 27 '14 at 10:04

2 Answers2

29

First, let's review what you seem to know:

  1. Ruby requires you to define local variables before you use them.
  2. You can run Ruby code on lines outside of a filter using - ....
  3. You use #{...} markup to interpolate Ruby code inside a filter.

You say you want to run each, but presumably you want output from this; since the result of #{...} is turned into a string and put in your code, what you really want (probably) is map:

%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.

Phrogz
  • 296,393
  • 112
  • 651
  • 745
  • so can I do something more complicate like my very last code sample? the whole `var data`? – Radek May 03 '11 at 04:40
  • @Radek Yes, you can produce any output you want. The easiest way to produce a large literal like that is by first requiring the JSON library in Ruby `require "json"` and then creating a Ruby array with a Hash with all the sub-structures you want, and then simply `var data = #{ruby_variable.to_json};`...but we already covered this in [your other question](http://stackoverflow.com/questions/5812789/what-is-the-hash-structure-to-produce-json). – Phrogz May 03 '11 at 12:34
2

The haml documentation for filters states that you can interpolate Ruby code using #{}

- flavor = "raspberry"
#content
  :textile
    I *really* prefer _#{h flavor}_ jam.
Jeff Perrin
  • 8,094
  • 1
  • 23
  • 19