Fork me on GitHub

Routing

Although Caboose sits on top of express, Caboose has it's own router.


The basics

The Caboose routing DSL seeks to be flexible and simple. The routes file is loaded as a module and should export a single function. This function have access to the routing DSL methods.

Here's a very simple routes.coffee file to demonstrate the structure:

    
module.exports = ->
  # Route requests for GET / to the ApplicationController's index action
  @route '/', 'application'

  # Route requests for GET /posts to the PostsController's index action
  @route '/posts', 'posts'
  # Route requests for POST /posts to the PostsController's create action
  @route 'post /posts', 'posts#create'
    

Each route has 4 properties; The method, path, controller and action.

The path must be specified in the first arguments to @route and can optionally include the method. If no method is included it is defaulted to GET. All properties except for the path can also be specified in the second argument.

For instance, the following lines are all equivalent.

@route     '/path', 'controller'
@route 'get /path', 'controller'
@route     '/path', 'controller', {method: 'get', action: 'index'}
@route 'get /path', 'controller', {action: 'index'}

@route     '/path', {controller: 'controller'}
@route     '/path', {controller: 'controller', method: 'get'}
@route     '/path', {controller: 'controller', action: 'index'}
@route     '/path', {controller: 'controller', method: 'get', action: 'index'}
@route 'get /path', {controller: 'controller', action: 'index'}
    

Parameters

Parameters can be specified on routes in the same way as frameworks like express or rails by putting a colon before the route segment. These parameters will then be available from the @params object with a controller action.

So for a route like:

@route '/users/:id', 'users#show'
    

You can then access the user's id from a controller action like this:

class UsersController extends Controller
  show: ->
    console.log "The user's id is #{@params.id}"
    @render()
    

You can also add parameters to any route, by setting them on the options object, like this:

@route '/superheroes/green-lantern', 'superheroes', {
  codename: 'green lantern'
}
    

Any parameters that you set on a route will be available in the @params object from within controller action. So in this case, you could access the codename of the /superheroes/green-lantern from the index action on the SuperheroesController at @params.codename.

Parameter Conditions

Conditions can be set on any parameters in a route. Just pass a conditions object to the route:

# Restrict id to the string 'green-lantern'
@route '/superheroes/:id', 'superheroes#show', {
  conditions: {':id': 'green-lantern'}
}

# Restrict id to any of the strings 'green-lantern', 'alan-scott' or 'hal-jordan'
@route '/superheroes/:id', 'superheroes#show', {
  conditions: {
    ':id': ['green-lantern', 'alan-scott', 'hal-jordan']
  }
}

# Restrict the id to any string matching the regular expression /green/i
@route '/superheroes/:id', 'superheroes#show', {
  conditions: {':id': /green/i}
}

# Restrict the id to an integer
@route '/superheroes/:id', 'superheroes#show', {
  conditions: {
    ':id': (id, request) ->
      parseInt(id).toString() is id
  }
}
    

Resourceful Routing

Resourceful routing is available with the resources method:

@resources 'superheroes'
    

This will create all resourceful routes for the SuperheroesController. This is the equivalent of:

@route        '/superheroes',          'superheroes#index'
@route        '/superheroes/new',      'superheroes#new'
@route 'post   /superheroes',          'superheroes#create'
@route        '/superheroes/:id',      'superheroes#show'
@route        '/superheroes/:id/edit', 'superheroes#edit'
@route 'put    /superheroes/:id',      'superheroes#update'
@route 'delete /superheroes/:id',      'superheroes#destroy'
    

Resources can also be embedded.

@resources 'users', ->
  @resources 'posts'
    

This will create all resourceful routes for both the UsersController and the PostsController. This is the equivalent of:

@route        '/users',          'users#index'
@route        '/users/new',      'users#new'
@route 'post   /users',          'users#create'
@route        '/users/:id',      'users#show'
@route        '/users/:id/edit', 'users#edit'
@route 'put    /users/:id',      'users#update'
@route 'delete /users/:id',      'users#destroy'
@route        '/users/:users_id/posts',          'posts#index'
@route        '/users/:users_id/posts/new',      'posts#new'
@route 'post   /users/:users_id/posts',          'posts#create'
@route        '/users/:users_id/posts/:id',      'posts#show'
@route        '/users/:users_id/posts/:id/edit', 'posts#edit'
@route 'put    /users/:users_id/posts/:id',      'posts#update'
@route 'delete /users/:users_id/posts/:id',      'posts#destroy'
    

Domain Routing

@domain 'caboosejs.com', ->
  @route '/', 'caboosejs_com'

@domain 'caboosejs.org' ->
  @route '/', 'caboosejs_org'

@route '/foo', 'foo', {
  conditions: {domain: 'caboosejs.com'}
}
    

Subdomain Routing

@subdomain 'www', ->
  @route '/', 'caboosejs_com'

@subdomain ((subdomain, request) ->
    # put the subdomain into the params object
    request.params.codename = subdomain
  ), ->
  @route '/', 'caboosejs_org'

@route '/foo', 'foo', {
  conditions: {subdomain: 'foo'}
}