Using AJAX and HandlebarsJS in Ruby on Rails

September 8, 2016 | Javascript, Ruby, Web Development

AJAX, HandlebarsJS, Rails Tutorial

In this post I’m going to show you how to create a simple single page Rails app using AJAX and HandlebarsJS. This is a great pattern to use for small, dynamic apps that’s quick and easy to implement.

You’ll need:
– Knowledge of Ruby, Ruby on Rails, Javascript, and JQuery
– The active_model_serializers gem, to serialize our model instances
JSONView Chrome Extension, to make any of our JSON rendered in the browser more readable
– A basic understanding of HandlebarsJS
– Some knowledge of how AJAX works

The Rails app used in this tutorial is available here:
https://github.com/cassaram09/rails-ajax-handlebars-demo

1. Initialize a new rails project

2. Add active_model_serializers gem to gemfile and bundle

3. Add JS files to your asset pipeline. Download handlebarsJS and add to vendor/assets/javascripts folder. In App/assets/js/, remove require_tree and replace with require notes and require handlebars (full file name).

4. Generate a new resource Note:

5. Add a title and content to Note migration as strings. We want our notes to have some attributes.

6. Migrate the database

7. In the note_serializers file, add :title, and :content to the Note attributes. If you don’t have a serializer in Rails yet, you can add one yourself – add a “serializers” folder in your “app” folder and create the file “note_serializers.rb”.

8. Build out your Note Controller. You’ll only need to add to respond_to for the index action, since this is the only action that needs to render both HTML and JSON. The other views only need to render JSON responses.

9. Check your JSON by navigating to /notes.json in your browser. Assuming you stubbed out some Note instances (which you can and should do in your terminal) and did everything correctly, JSON should be rendered in the browser. If you haven’t installed the JSONView Chrome Extension, now would be a good time. You should see something similar to the following:

10. Build out a basic index view. Later we’ll add our HandlebarsJS templates to this file. “new-note” is where our note form will reside. “notes-block” is where our notes will be loaded to, via AJAX.

11. Next, let’s start building our Create Note functionality. First, we’ll want to build a class for our Note, complete with a constructor and prototype methods:

Let’s take a second to discuss what’s happening here. In the constructor, we’re defining a Note object, whose attributes will come a hash passed as an argument. The other four methods will be used for rendering each Handlebars template as necessary. We could also make a prototype method for formatting the Note object’s data, if that was necessary (eg a created_at date).

12. Implement functions to compile our Handlebars templates. Let’s take a look at what’s being called in the render prototype functions:

Each of these functions is called inside our $(document).ready() function so they are available after the page has loaded. Using JQuery, we grab the html from our Handlebars templates, defined in index.erb.html, and then compile it and store it in a variable.

13. Add Handlebars templates to index.erb.html, below our HTML.

It looks like a lot, but it’s not bad at all! We’re creating a script tag, giving it a unique ID, and specifying it’s type as “text/x-handlebars-template” so Handlebars knows this is a Handlebars template. Inside the script tags is vanilla HTML, with a small twist – we pass variables wrapped in double curly braces to indicate this is where we’ll be injecting information. It’s best practice to use the names of the model attributes – eg, {{id}}, {{content}}, {{title}}, etc. as we’ve defined in our Note class.

14. Now all we have to do is define our AJAX functions!

Our first function, indexNotes(), sends a GET request as soon as the page loads to retrieve all Notes. We iterate over the response, creating each a Note object for each node and rendering it to the page using JQuery.

Our first function, newNote(), sends a GET request, creates a new (blank) Note object, and renders the newNote template to the page using JQuery.

The createNote() function executes when the newNote we just rendered is submitted. It serializes the data and sends a POST request tothe application. The responses is a JSON object, which is used to create a new Note object. The indexNote() template is rendered using this object’s attributes and injected into the page.

The showNote() function sends a GET request to the application. The JSON response is passed as an argument to create a new Note. The showNote template is rendered using this Note object and then injected into the page.

The editNote() function is called when, after a the showNote template has been rendered, a user clicks on the edit button. This triggers another GET request, but this time for the editNote template. Another Note object is created and the editNote template is rendered using it’s attributes. The template is injected into the page and the form fields are prefilled with the Note object’s attributes.

On submission of the edit form, the updateNote function is triggered, sending a POST request to the application. Once again, a Note object is created and the indexNote template is rendered using it’s information. It is then injected into the page after the HTML in it’s block has been cleared.

Finally, we have our deleteNote function. This function sends a POST request to the application. Two things happen here: since we’re being routed to the delete action in our controller, we are deleting the Note, but then we’re also clearing it’s node on the page.

15. Make sure to call your functions on document load!

And there you have it! We’ve built a basic app the uses AJAX and Handlebars for CRUD , with Rails as a base.

Bonus: If you want to keep your Handlebars templates in a separate file, check out the following blog post:
http://berzniz.com/post/24743062344/handling-handlebarsjs-like-a-pro

Comments or suggestions? Leave them below!

Leave a Reply

Your email address will not be published. Required fields are marked *