Bring Rails data to javascript with Gon

on Gon, JS Rails Variables

Using Rails data in javascript is a very common need, especially for SPA (Single Page Application) with AngularJS, Backbone.js, Ember... or only pure javascript applications.

We have some ways to make this

Assign to javascipt variable in views
#/views/layouts/application.html.erb
<script type="text/javascript">
var g_currentUser = <%= raw current_user.to_json %>;
</script>

Will render

<script type="text/javascript">
      var g_currentUser = {"id":1,"email":"[email protected]","created_at":"2015-02-01T07:46:33.303Z","updated_at":"2015-02-01T07:58:16.516Z"};
    </script>

g_currentUser is global variable, so we can use it in javascipt files.

Render data to "data" HTML attribute

<%= content_tag(:span, id: 'initial-vars', class: 'invisible', data: {current_user: current_user}){} %>

Will render

<span id="initial-vars" class="invisible" data-current-user="{&quot;id&quot;:1,&quot;email&quot;:&quot;[email protected]&quot;,&quot;created_at&quot;:&quot;2015-02-01T07:46:33.303Z&quot;,&quot;updated_at&quot;:&quot;2015-02-01T07:58:16.516Z&quot;}"></span>

Then

var g_currentUser = $('span#initial-vars').data().currentUser;

Use Gon

Above solutions seem to be not very clean and manageable, especially when we need more data instead of only g_currentUser.

Gon helps us to archive our need easier and cleaner.

Setup

Setup gon is easy

  • Add gem 'gon' to Gemfile and run bundle install
  • Insert <%= include_gon %> in head tag of layouts (you can bring it to anywhere you want to use it if you don't want Gon available in all views. Actually, put it in layout is the most case)
Set variables from controller/view (often from controller)
gon.currentUser = current_user
gon.siteName = 'Awesome Site'
# OR
gon.push({
  currentUser: current_user,
  siteName: 'Awesome Site'
})
Use it in javascript

Above code will generate this in rendered page

//<![CDATA[
window.gon={};gon.currentUser={"id":1,"email":"[email protected]","created_at":"2015-02-01T07:46:33.303Z","updated_at":"2015-02-01T07:58:16.516Z"};gon.siteName="Awesome site";
//]]>

So, in javascript we can use them as normal variables

console.log(gon.currentUser);
console.log(gon.siteName);

Output

Object {id: 1, email: "[email protected]", created_at: "2015-02-01T07:46:33.303Z", updated_at: "2015-02-01T07:58:16.516Z"}
Awesome site
Tips
  • Use <%= include_gon(namespace: 'App') %> instead of <%= include_gon %> to use App.currentUser instead of gon.currentUser
  • Include Gon in body instead of head when using turbolinks to make Gon reload in each pave moving
  • Gon be be used with Rabl, see Guide
  • Gon be be used with JBuilder, see Guide
  • Use gon.watch to reload Gon variables from Rails asynchronously
  • Gon will cause gon is not defined javascript error if no variable was pushed to Gon. Always push atleast 1 variable to Gon to prevent this
  • See Gon Wiki for more information

A full stack developer with Ruby on Rails as the main framework. Eager to learn and share.