Usage with RABL

takiy33 edited this page Jul 22, 2015 · 8 revisions

With gon, variables can assign logic to templates with RABL.

The following example involves passing a 'Post' model with attributes :title and :body to a js variable.

1. Add gon and RABL to Gemfile

Add RABL to the Gemfile before requiring gon, as gon checks the Rabl constant.

Gemfile

gem 'rabl'
...
gem 'gon'

2. Create a RABL template

For Rails 3.2 name your template file: app/views/posts/index.rabl

For Rails <3.2 name your template file with a json extension: app/views/posts/index.json.rabl

collection @posts => 'posts'
attributes :id, :title, :body

3. Map gon to RABL template.

If RABL template is in default directory for action:

app/controllers/posts_controller.rb#index

def index
    @posts = Post.all # Rabl works with instance variables of controller
    gon.rabl
      
    # Remaining controller logic
end

If RABL template is in a different directory:

app/controllers/posts_controller.rb#index

def index
    @posts = Post.all # Rabl works with instance variables of controller
    gon.rabl :template => "app/views/posts/show.rabl", as: "posts" # in Rails versions <3.2 it should be: show.json.rabl
      
    # Remaining controller logic
end

Thats it! Now a js gon.posts variable is available containing an array of post objects with attributes :id, :title and :body.

To call this variable in your js:

alert(gon.posts)
alert(gon.posts[0])
alert(gon.posts[0].post.body)

NOTE: Remember to include_gon tag in your html head area. Read more about this in the common usage section.

Aliases in RABL

If you don't use alias in Rabl template:

collection @posts
....

instead of using that:

collection @posts => 'alias'
....

Rabl will return you an array and gon by default will put it to variable gon.rabl

Two ways how you can change it - using aliases or you can add alias to gon mapping method:

# your controller stuff here

gon.rabl :as => 'alias'

Locals

You can pass locals option to gon.rabl:

app/controllers/posts_controller.rb#index

def index
    @posts = Post.all # Rabl works with instance variables of controller
    gon.rabl as: 'posts'
    gon.rabl locals: { posts: Post.where(category: 'News') }, as: 'news'
      
    # Remaining controller logic
end

After that you can access from JS both collections:

alert(gon.posts)
alert(gon.news)