Fork me on GitHub

The Skinny

// define a route
router.get( '/:beverage/near/:location(.:format)' )
      .to( 'beverage.byLocation' )

// convert a URL to a params object
router.first( '/coffee/near/90210', 'GET' )

// =>
{
  controller: 'beverage',
  action: 'byLocation',
  beverage: 'coffee',
  location: 90210,
  method: 'GET'
}


// generate a URL from a params object
router.url({
  controller: 'beverage',
  action: 'byLocation',
  beverage: 'coffee',
  location: 90210,
  format: 'json'
})

// => '/coffee/near/90210.json'

Installation

Install via npm

npm install barista

Use it in your app

var Router = require('barista').Router
  , router = new Router

Defining routes

A simple example

// a GET request to '/products'
router.match( '/products', 'GET' )
      .to( 'products.index' )

// =>
{
  controller: 'products',
  action: 'index',
  method: 'GET'
}

Rails-esque variable names

router.match( '/products/:id', 'GET' )
      .to( 'Products.show' )

router.match( '/profiles/:username', 'GET' )
      .to( 'Users.show' )

// things enclosed in parens are optional
router.match( '/products/:id(.:format)', 'GET' )
      .to( 'Products.show' )

Convenience methods

router.get( '/products/:id(.:format)' )
      .to( 'Products.show' )

router.put( '/products/:id(.:format)' )
      .to( 'Products.update' )

router.post( '/products' )
      .to( 'Products.create' )

router.del( '/products' )
      .to( 'Products.destroy' )

Route globbing

router.get('/timezones/*tzname')
      .to( 'Timezones.select' )

router.first( '/timezones/America/Toronto', 'GET' )

// =>
{
  controller: 'Timezones',
  action: 'select',
  tzname: 'America/Toronto',
  method: 'GET'
}

// a "catch-all" route:
router.match( '/*path(.:format)' )
      .to( 'Errors.notFound' )


router.first( '/somewhere/that/four-oh-fours.json', 'GET' )

// =>
{
  controller: 'Errors',
  action: 'notFound',
  path: 'somewhere/that/four-oh-fours',
  format: 'json',
  method: 'GET'
}

Resolution & dispatching

router.first

// get the first route that matches

params = router.first( '/products/15', 'GET' )

// returns a params object, or false if nothing matches

// go all callback on this shit

router.first( '/products/15', 'GET', function(params){
  // passes a params object in
  // this has not been well thought out.
})

router.all

// if you want all matching routes...

params_array = router.all( '/products/15', 'GET' )

// => [ params, params, params... ]

Resources

REST resources

router.resource( 'BlogPosts' )

// is equivalent to:

router.get( '/blog_posts(.:format)' )
      .to( 'BlogPosts.index' )

router.get( '/blog_posts/add(.:format)' )
      .to( 'BlogPosts.add' )

router.get( '/blog_posts/:id(.:format)' )
      .to('BlogPosts.show' )

router.get('/blog_posts/:id/edit(.:format)' )
      .to( 'BlogPosts.edit' )

router.post('/blog_posts(.:format)' )
      .to( 'BlogPosts.create' )

router.put('/blog_posts/:id(.:format)' )
      .to( 'BlogPosts.update' )

router.del('/blog_posts/:id(.:format)' )
      .to( 'BlogPosts.destroy' )

Nested routes & resources

// resources can nest both routes and deeper resources
router.resource( 'BlogPosts' )
      // nest on the collection
      .collection(function(){
        this.get( 'print(.:format)' )
            .to('BlogPosts.print')
      })
      // nest on the member
      .member(function(){
        this.resource( 'Comments' )
      })


router.first( '/blog_posts/5/comments' )

// =>
{
  controller: 'Comments',
  action: 'index',
  blog_posts_id: 5,
  method: 'GET'
}


router.first( '/blog_posts/print.pdf' )

// =>
{
  controller: 'BlogPosts',
  action: 'print',
  format: 'pdf',
  method: 'GET'
}

Conditions

Match conditions

router.get( '/:beverage/near/:zipcode' )
      .to( 'beverage.byZipCode' )
      .where({
        // an array of options
        beverage: [ 'coffee', 'tea', 'beer', 'warm_sake' ],
        // a regex pattern
        zipcode: /^\d{5}(-\d{4})?$/
      })

Mixing conditions

router.get( '/:beverage/near/:location' )
      .to( 'beverage.byLocation' )
      .where({
        location: [
          // could be a zip code
          /^\d{5}(-\d{4})?$/,
          // OR a postal code
          /^[A-Z]{1}\d{1}[A-Z]{1} *\d{1}[A-Z]{1}\d{1}$/,
          // OR the word 'me'
          'me'
        ]
      })

URL generation

Turn a params object into a URL

// assuming:
router.resource( 'products' )

// then
router.url( {
  controller: 'products',
  action: 'show',
  id: 5
} )

// => '/products/5'

router.url( {
  controller: 'products',
  action: 'show',
  id: 5,
  format: 'json'
} )

// => '/products/5.json'

Extra params

// you can optionally include extra params as a query string
router.url({
  controller: 'products',
  action: 'show',
  id: 5,
  format: 'json',
  love: 'cheese' // <--------
}, true )

// => '/products/5.json?love=cheese'