1

I'm new to Backbone so as a learning exercise I'm trying to set up a simple application with a Rails backend. I'm struggling to separate Rails api routes and Backbone routes. For instance my Backbone router currently looks like this:

class App.Routers.LawAppRouter extends Backbone.Router
  routes:
    '': 'index'
    'flows/:id': 'showFlow'

index: ->
  flows = new App.Collections.Flows()
  flows.fetch().done =>
    view = new App.Views.Flows(collection: flows)
    $('#container').html(view.render().el)    

showFlow: (id) ->
  alert('in showFlow)

What I would like to do is to have the Rails API live under "api/v1/resource" namespace while Backbone will handle simple "/resource" routes and then call the API in the handler functions.

Initially I created a Flow model

class App.Models.Flow extends Backbone.Model

a collection

class App.Collections.Flows extends Backbone.Collection
  url: 'api/v1/flows'
  model: App.Models.Flow

and an index view

<ul>
  <% for flow in @flows.models: %>
    <li>
      <a href="<%= flow.url() %>"><%= flow.get('title') %></a>
    </li>
  <% end %>
</ul>

Written this way, flow.url() returns

api/v1/flows/:id

which directly hits the API. Instead I would like flow.url() to generate a client-side route

flows/:id

So I changed the model to be

class App.Models.Flow extends Backbone.Model
  clientSideUrl: ->
    "flows/#{@id}"

And the index view to

<a href="<%= flow.clientSideUrl() %>"><%= flow.get('title') %></a>

Which now generates

flows/:id

which, as far as I understand, should match this Backbone route

'flows/:id': 'showFlow'

However, instead it keeps hitting the API at /flows/:id which throws an error since that route does not exist in Rails.

  1. What am I missing here?
  2. Why is the Backbone route not being triggered?
  3. Is this the correct way to separate client-side and server-side routes in Backbone?

Thank you!

Dmitry
  • 161
  • 1
  • 1
  • 10

1 Answers1

0

If you are not using pushState then the url in the href attribute should have been :

<a href="<%= #/flow.clientSideUrl() %>"><%= flow.get('title') %></a>

Since the # is missing its directly trying to navigate to the url instead of instantiating the router.

If you are using html pushState then you need to follow something like this: https://stackoverflow.com/a/9331734/741108

If you want your Model/Collection and Router url look similar, then you can make use of $.ajaxPrefilter

// root = 'http://your.domain.com/api/v1' 
$.ajaxPrefilter(function(options,orginalOptions,jqXHR){
    options.url = root + options.url;    
});

Each ajax call will now go thru the prefilter before the call is actually made.

Thus models(urlRoot) and collections(url) can have relative url in their definitions which can look similar to the Routes url and still, when the server call is made the complete url is framed in the prefilter.

Community
  • 1
  • 1
Balaji
  • 1,009
  • 7
  • 21