Routerer
This is how I route.
- Mims ?
Slim, testable router.
Install
bower
bower install --save will-ob/routerer
npm
npm install --save git+ssh://git@github.com:will-ob/routerer.git
Use
The easiest way to define a route:
var routerer = require('routerer'),
MyRouter = routerer.createRouter(_, Backbone),
addRoute = routerer.addRoute;
addRoute(MyRouter, "", IndexPage);
Add some more:
// Router Path Initializing Function
addRoute(MyRouter, "login", loginPageInit);
addRoute(MyRouter, "sign-up", signUpPageInit);
addRoute(MyRouter, "account", accountPageInit);
addRoute(MyRouter, "user/:id/images/:page", userImagesPageInit);
Routes can also be added as you might expect if you were subclassing the Backbone.Router. Buhhhht, dooooon't - that will take us right back to where we started. (see 'Ok, but why')
When you've got everything configured,
var myRouter = new MyRouter();
Backbone.history.start();
Ok, but why
Well, testing - and we'll get to that. But first, uniformity:
Every view gets an el, a map of url params, and a reference to the router.
// navigating to 'user/:id/images/:page', as is
// declared above, is the same as calling:
userImagesPageInit({
el: $('page-el-owned-by-router'),
router: myRouter,
args: {id: "24", page: "742"}
});
Views can then set themselves up with any configuration required.
userImagesPageInit = function(opts) {
if(opts == null){ opts = {}; };
if( opts.router.logged_in ){
opts.router.navigate('', true);
} else {
opts.el.html(signUpForm);
}
// Always return a teardown / close method
return function(){
// free all the memory!
$(opts.el).html("");
}
}
The router will always call the close method before navigating to a new page.
Without some enforced consistency, your router slips into tragedy. With this set-up, the router is just your routes. You couldn't write a routeHandler if you tried. figure of speech, I'm sure you're quite capable.
At the end of the day, the complexity of your router stays pretty constant. There's no chance developers will have to load an exponentially increasing amout of complexity into their heads each time they want to add a route.
Testing your pages
When you test your views, you don't have to pass them a real router.
context("user is signed in", function(){
beforeEach(function(){
this.router = {
navigate: function(){}
}
});
it("routes to index", function(){
var spy = sinon.spy(this.router, 'navigate'),
page = new LoginPage({router: router});
expect(spy.calledOnce).to.be.true;
expect(spy.firstCall.args[0]).to.eql('');
expect(spy.firstCall.args[1]).to.eql(true);
});
});
License
The MIT License (MIT)
Copyright (c) 2014 Will O'Brien