Search code examples
javascriptruby-on-railsprototypejs

How to pass Ruby variables to a JavaScript function in a Rails view?


I'm wondering what the best practice is for passing variables to JavaScript functions in a rails view. Right now I'm doing something like:

<% content_for :javascript do %> 
  <script type="text/javascript">
    Event.observe(window, 'load', function(){          
        js_function(<%= @ruby_array.to_json %>, <%= @ruby_var %>); )}
  </script>
<% end %>

Is this the right way to go about it?


Solution

  • A few options:

    escape_javascript

    Alias: j.

    Works only on strings.

    Escapes characters that can have special meanings in Javascript strings, like backslash escapes, into a format suitable to put inside Javascript string literal quotes.

    Maintains html_safe status of input, so needs html_safe otherwise special HTML chars like < would get escaped into &lt;.

    <% a = "\\n<" %>
    <%= javascript_tag do %>
      '<%= j(a)           %>' === '\\n&lt;'
      '<%= j(a).html_safe %>' === '\\n<'
    <% end %>
    

    to_json + html_safe

    As mentioned by Vyacheslav, go upvote him.

    Works because JSON is almost a subset of Javascript object literal notation.

    Works not only on hash objects, but also on strings, arrays and integers which are converted to JSON fragments of the corresponding data type.

    <% data = { key1: 'val1', key2: 'val2' } %>
    <%= javascript_tag do %>
      var data = <%= data.to_json.html_safe %>
      data.key1 === 'val1'
      data.key2 === 'val2'
    <% end %>
    

    data- attributes

    Add values to attributes, retrieve them with Javascript DOM operations.

    Better with the content_tag helper:

    <%= content_tag 'div', '', id: 'data', data: {key1: 'val1', key2: 'val2'} %>
    <%= javascript_tag do %>
      $('#data').data('key1') === 'val1'
      $('#data').data('key2') === 'val2'
    <% end %>
    

    Sometimes called "unobtrusive Javascript".

    gon

    Library specialized for the job: https://github.com/gazay/gon

    Probably the most robust solution.

    Gemfile:

    gem 'gon'
    

    Controller:

    gon.key1 = 'val1'
    gon.key2 = 'val2'
    

    Layout app/views/layouts/application.html.erb:

    <html>
    <head>
      <meta charset="utf-8"/>
      <%= include_gon %>
    

    View:

    <%= javascript_tag do %>
      gon.key1 === 'val1'
      gon.key2 === 'val2'
    <% end %>
    

    See also