Node for Rails developers: using Compound.js
Ruby on Rails developers turning to Node.js may find a soft landing with Compound.js and CoffeeScript
There’s no need to explain how wonderful Ruby on Rails is as a MVC web development framework. It’s mature, well structured, packages (gems) rich, production ready, etc. However performance could be argued, this is not a benchmark post. There’s no need in saying “if you want Rails then stick with Rails”. This post is for developers who decided turning to Node, wishing to enjoy it’s benefits, in this case in a Railsy paradigm.
Node can be used in a diversity of ways, and this is just one simple example. See “The Tip of the Iceberg” at the end of this article in that context. In our context, gladly enough and as mentioned in my earlier post, Node’s community is rapidly expanding and so by now you can find several frameworks that are inspired by Rails. My favorite is CompoundJS, and in the next couple of minutes I’ll try to review it in brief and build together a small To-Do List (what else) using Compound, Coffeescript, Jade, Stylus and AngularJS (databases and tests will be addressed in a different posts).
This use case may be argued a classic Single Page Application with Compound acting as the backend (Restful API, layout and assets) and Angular doing most of the client-side rendering. You should keep in mind this isn’t a Rails tutorial, nor an Angular tutorial, not even a profound Compound tutorial. It’s an intro, relying on the assumption you have sufficient experience that will allow you to leverage these principals into a well structured, highly performing application.
Lastly, you may ask “why should I do this in Node?”, see “The Tip of the Iceberg” at the end of the article to try and answer that. Ready to code? Let’s go.
This post assumes you have Node and NPM installed and ready to go. It also assumes you have sufficient experience with Rails, it’s directory structure, generators, MVC design pattern etc. Otherwise, you may need to do some homework before fully utilizing this text.
I chose to initialize my project using Coffescript. There’s quite a debate going on right now about it, especially with ECMAScript 6 scent in the air, so many Node developers might turn from it, but for the sake of this topic (“Railsy Node” if you like) I want to use in my stack. I also chose to stick with Jade as a template engine, Stylus as a CSS pre-compiler, and neglected a database at this point since it’s a topic on it’s own. Needless to say, Compound (based on the robust and flexible Express.js engine) gives you the complete liberty to choose and integrate any package you prefer, out of the box or as a 3rd party alike.
We’ll start by installing compound globally, and then initiating our project:
[sudo] npm install -g compound
compound init compound-angular-todo —coffee —tpl jade
The result is very much like what you would have expect from Rails to generate. We’ll finalize the setup by installing “node-dev” and installing the other packages required by Compound using `npm install`, just like you’d do with `bundle install` command.
npm install —save-dev node-dev
We’re ready to run our server. Let’s give it a try:
Compound server listening on 0.0.0.0:3000 within development environment
Models, Controllers, Views and Routes. You know the drill.
Compound provides generators, similar to those you may find in Rails. Getting started with CRUD as simple as you’re used to. In this simple app I will discard authentication and turn directly to creating a Single Page Application with Compound acting both as a Resftul API, layout dispatcher and assets compiler. I will also (sadly) skip tests at this time, trying to keep this post short and minimalistic. These topics would be covered on another occasion.
compound g controller tasks
compound g model task description:string completed:boolean created_at:date
Now, for all of our sakes, I’ll make a few shortcuts, likes so:
- Will remove `public/index.html` static intro page
- Will include AngularJS in the primary `application_layout.jade` template, and slightly alter it to fit our project.
- Will define our basic “tasks” routes in `config/routes.coffee`. Notice I’m skipping our regular CRUD paradigm here for two reasons:
A) Because it’s not written in stone, although considered a good practice. I intentionally approach differently as a preparation for realtime Socket.io implementation.
B) This is a very simple example and like to keep it as light weight as possible, discarding as much code as I can.
- I will also create a basic partial skeleton using Jade for my tasks controller, that could be found on `app/views/tasks/index.jade`.
- Finally I will write a simple AngularJS app that handles the events on our To-Do app. That could be found on `app/assets/coffeescript/ application.coffee`. What going on is basic: loading our tasks list from the server on init, and then updating it on new, edited, completed or removed tasks events.
Our app is ready to go. Emulating production (and even in development with less caching) show some sleek response times of 1ms or less per request (as JSON or HTML).
Pushing to Production
Now that our application is ready, deploying it is a breeze. Compound supports assets consolidation, as well as a config file for each different environments (development, test, production) to allow each one with different characteristics. NPM is (almost) as rich as Ruby Gems, so you can easily find more packages to support your debut and production performance (CDNs, cache, Redis, database adapters, Riak, etc). All that’s left for me now is to create an Heroku application and deploy it using Git. More information about deploying Compound to Heroku can be found on Compound’s official site. Needless to say, Compound will deploy just as easy to other platforms like EC2, Nodejitsu and others.
Here’s our Compound-Angluar-Todo app, Rails-style, live: http://compound-angular-todo.herokuapp.com
Review the source code here: https://github.com/sagish/compound-angular-todo
The Tip of the Iceberg
A few questions must rise after following this tutorial, the most obvious one being “Why would you do a Node app in a Rails paradigm, instead of just doing it with Rails?”, well…
But the main reason I would do a Single Page Application using Node is because with a little adjustment we can create a Realtime Application, that receives and responds to events using a scalable implementation of Socket.io (like the wonderful Trello or Asana), that updates without any reloads needed, that is lightweight and growing more efficiently on the server with each update - and we can do it either by following a specially-designed-for-that-cause framework (like Meteor or Derby) or in a way we know and have complete control over (thanks to Express) like a Rails inspired MVC.