35

I am just starting to look at MVC structure, first i looked at how backbone.js worked, and now I have just completed rails for zombies, by Code School. I know that I haven't delved too far into any of this, but I had a question to begin with.

Can you use these libraries together?

I have learned how to create models, views, etc in both, but when creating a real application do you use both backbone and rails?

If so...

When do you use a backbone.js model vs. a rails model?

Maybe I am just getting ahead of myself and need to keep practicing and doing tutorials but I couldn't seem to find anything directly on this.

Thanks!

3 Answers 3

74

Before anything else I'd suggest taking a look at thoughtbot's Backbone.js on Rails book, which is a great starting point, although aimed at an intermediate to advanced audience. I bought this book having already worked with rails but as a total backbone.js beginner and it has served me very well.

Beyond that, there are some fundamental issues with combining these frameworks which go beyond the details covered in this book and other books. Below are some things I'd suggest you think about, from my own experiences pairing RoR and backbone.js. This is a long answer and strays a bit from the specifics of your question, but I hope it might help you out in the "big picture" sense of understanding the problem you're facing.

Rails: Web Framework vs API

The first thing you confront when using backbone.js on top of a rails application is what to do about views, but this is really just the surface of a much deeper issue. The problem goes to the very heart of what it means to create a RESTful web service.

Rails is set up out of the box to encourage its users to create RESTful services, by structuring routing in terms of a set of resources accessed at uniform URIs (defined in your routes.rb file) through standard HTTP actions. So if you have a Post model, you can:

  • Get all posts by sending GET request to /posts
  • Create a new post by sending a GET request to /posts/new, filling out the form and sending it (a POST request) to /posts
  • Update a post with id 123 by sending a GET request to /posts/123/edit, filling out the form and sending it (a PUT request) to posts/123
  • Destroy a post with id 123 by sending a DELETE request to /posts/123

The key thing to remember about this aspect of Rails is that it is fundamentally stateless: regardless of what I was doing previously, I can create a new Post simply by sending a POST request with a valid form data to the correct URI, say /posts. Of course there are caveats: I may need to be logged in (have a session cookie identifying me), but in essence Rails doesn't really care what I was doing before I sent that request. I could follow it up by updating another post, or by sending a valid action to whatever other resources are made available to me.

This aspect of how Rails is designed makes it relatively easy to turn a (Javascript-light) Rails web application into an API: the resources will be similar or the same, the web framework returning HTML pages while the API (typically) returns data in JSON or XML format.

Backbone.js: A new stateful layer

Backbone is also based on RESTful resources. Whenever you create, update or destroy a backbone.js model, you do so via the standard HTTP actions sent to URIs which assume a RESTful architecture of the kind described above. This makes it ideal for integrating with RESTful services like RoR.

But there is a subtle point to be stressed here: backbone.js integrates seamlessly with Rails as an API. That is to say, if you strip away the HTML views and just use Rails for serving RESTful resources, integrating with the database, performing session management, etc., then it integrates very nicely with the structure that backbone.js provides for client-side code. Many people argue that there's nothing wrong with using rails this way, and I think in many ways they are right.

The complications arise though from the issue of what to do with that other part of Rails that we've just thrown away: the views and what they represent.

Stateful humans, stateless machines

This is actually more important than it may initially seem. HTML views represent the stateless interface that humans use for accessing the RESTful resources your service provides. Doing away with them leaves you with two access points:

  1. For humans: a rich, client-side interface provided by the backbone.js layer (stateful)
  2. For machines: a resource-oriented RESTful API provided by the rails layer (stateless)

Notice that there is no longer a stateless (RESTful) interface for humans. In contrast, in a traditional rails app with an API, we had something closer to this:

  1. HTML resources for humans (stateless)
  2. JSON/XML resources (API) for machines (stateless)

The latter two interfaces for accessing resources are much closer in nature to each other than the previous two. Just think for example of rails' respond_with, which takes advantage of the similarities to wrap various RESTful responders in a unified method.

Working together

This might all seem very abstract and beside the point, I know. To try to make it more concrete, consider the following problem, which gets back to your question about getting rails and backbone.js to work together. In this problem, you want to:

  • Create a web service with a rich client-side experience using backbone.js, with rails as the back end serving resources in JSON format.
  • Use pushState to give each page in the app a URL (e.g. /posts/123) which can be accessed directly (by entering it into the browser bar).
  • For each of these URLs, also serve an HTML page for clients without javascript.

These are not unusual demands for a modern web service, but they create a complex challenge. To make a long story short, you now have to create two "human-oriented" layers:

  1. Stateful client-side interface (backbone.js templates and views)
  2. Stateless HTML resources (Rails HTML views)

The complexity of actually doing this leads many nowadays to abandon the latter of these two and just offer a rich client-side interface. What you decide to do depends on your goals and what you want to achieve, but it's worth thinking about this problem carefully.

As another possible reference for doing that, I'd suggest having a look at O'Reilly's RESTful Web Services. It might seem odd to be recommending a book on REST in a question about Rails and Backbone.js, but actually I think this is the key piece that fits these very different frameworks together, and understanding it more fully will help you take advantage of the strengths of both.

6
  • 1
    wow this is fantastic. A little bit of a clarification: in the working together section, the idea of the solution you outlined would be to have a backbone app on the main page for example that uses AJAX or other methods to access JSON data rather than views, but also make HTML views that can be accessed organically by entering the URL? Thanks again for the thorough answer i really appreciated it! Commented Aug 12, 2012 at 18:18
  • 2
    Glad you liked it! Yes you hit on the key point, which I didn't try to answer in specifics because that would be a whole other discussion. It really depends on what kind of app you're building. For example, for an app I'm now doing, we've decided only to serve (js-free) HTML pages for GET requests to our resources. If users want to create or update these resources, they have to go through the rich interface (or potentially access the API directly). That's a design choice. You could also choose to drop the no-JS support but still have URLs for your resources, then you don't need rails views. Commented Aug 12, 2012 at 21:44
  • 2
    Terrific answer. If I could +2 I would. Thanks for spending the time to put together such a complete, thoughtful response.
    – steveax
    Commented Sep 30, 2012 at 3:48
  • You're very welcome! Please pass on the link to anyone else interested in this topic. Commented Sep 30, 2012 at 3:54
  • 1
    You shouldn't need to add a hash. All you need is a (Rails) route which renders the same root view of the app, then Backbone (with pushState enable) will recognize the path as a Backbone route and render the appropriate (Backbone) view. If a browser does not support pushState, Backbone will recognize this and redirect to the hash-prefixed path. Commented Jun 20, 2013 at 4:23
1

Yes, you can use both side by side. Backbone is for storing and manipulating data within the client browser. It generally needs a server to talk to and fetch the data from. This is where Rails comes in. You can have a web application without heavy client-side code. Backbone is for building out sites that feel more like apps--think of Gmail or Pandora.

I advise just learning Rails first. Once you can get static pages loading and styled as you wish, then understanding Backbone's place will make more sense

1

I've used rails as a backend server to serve a fairly large website, which included a few one-page apps (built in backbone).

I'd suggest the backbone-on-rails gem. The idea is that your rails server will serve up the backbone app as a script tag in one of your views. You keep your backbone app itself in the rails app/assets folder.

Backbone understands rails routing conventions, and you just need to give it a path to a json api that rails can almost generate for you with rails generate resource.

Other than the syncing between the models, your backbone apps and rails apps are fairly separate. Backbone and Rails don't have quite the same MVC model, but getting them to cooperate is pretty easy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.