Getting Rails Routes in a Ember application

Let's say that you are starting to implement a new Ember application to your existing Rails project and you want to build the new features and then migrate your existing ones gradually to Ember.

As you may know, Ember apps only communicates to the backend through APIs and they are usually a separated application.

The problem

In your nearly created Ember application you need to link or redirect the user to an old page that is still in Rails, how would you do that? Just hard code the url and hope it is not going to change in the meantime that you are migrating to Ember? I don't think so.

Given your Ember application only communicates to the backend through APIs, it would require you to create an endpoint to fetch the routes from the Rails app and then Ember would have access to it. That's not the best solution. Having an endpoint that retrieves the routes? Seriously?

There is other solution, and there is a gem you can use. :D

The solution

When I was searching for a solution to this problem, I found the js-routes gem that makes the hard work on the Rails side. It gets the routes and serve it in a Javascript file as a Javascript object that you can access easily on Ember or any other Javascript front-end framework.

To setup the js-routes in your Rails project, please follow the instruction at https://github.com/railsware/js-routes.

Now, to use it on the Ember app, you will need to create some helpers.

I'm using Ember CLI, so I will use the ES6 syntax.

Here is the first helper I needed, something to just return the string of the url so I could use in a HTML link tag.

// app/helpers/rails-route.js
import Ember from 'ember';

export function railsRoute(path, options) {  
  return RailsRoutes[path](options.hash);
}

export default Ember.Handlebars.makeBoundHelper(railsRoute);

To use it is really simple, just do something link this:

<a href="{{rails-route 'posts_path'}}">Link to Rails</a>  

The sencond helper I needed was one to generate the <a> tag as the Ember helper link-to does.

// app/helpers/link-to-rails.js
import Ember from 'ember';

export function linkToRails(text, path, options) {  
  var escapedText = Ember.Handlebars.Utils.escapeExpression(text);
  var classes = '';
  if(options.hash.class){
    classes = options.hash.class;
    delete options.hash.class;
  }
  var url = RailsRoutes[path](options.hash);
  return new Ember.Handlebars.SafeString('<a href="' + url + '" class="' + classes  + '">' + escapedText + '</a>');
}

export default Ember.Handlebars.makeBoundHelper(linkToRails);

Example:

{{link-to-rails 'Link to Rails' 'posts_path' class='btn' }}

Note: On js-routes gem I have choosen to export the routes to a RailsRoutes variable instead of it's default Routes.

Wrapping up

This is just a simple solution that you can take advantage for the meantime that you have both Ember and Rails application working together as one application.

This solution should be temporary, at least until you have all your routes setted up on the Ember app. Just because I don't really feel confortable sharing it in one JS file all the routes that my app has, even having the option to exclude things like /api and /admin that js-routes provides. It's your call, but use wisely.