Skip to content

Instantly share code, notes, and snippets.

@mxriverlynn
Created December 13, 2012 17:06
Show Gist options
  • Save mxriverlynn/4277997 to your computer and use it in GitHub Desktop.
Save mxriverlynn/4277997 to your computer and use it in GitHub Desktop.
Backbone.ModelRouter - Resolve an :id parameter is a `.modelRoutes` hash, to load a model and then run the callback method with the specified model as the arguments, instead of the id parameter
// Backbone.ModelRouter
// --------------------
//
// v0.0.0
//
// Resolve an :id parameter is a `.modelRoutes` hash, to load
// a model and then run the callback method with the specified
// model as the arguments, instead of the id parameter.
//
// Copyright (C) 2012 Muted Solutions, LLC. All Rights Reserved.
//
// Example:
// ```js
// Backbone.ModelRouter.extend({
// modelRoutes: {
// "models/new": "newModel",
// "models/:id": "showModel",
// "models/:id/action: "modelAction",
// "models/:id/subModel/:subId: "subModelAction"
// },
//
// newModel: function(model){
// model.isNew(); // => true
// },
//
// showModel: function(model){
// model.id; // => the id from the route... #models/1
// },
//
// modelAction: function(model){
// model.id; // => the id from the route... #models/1
// },
//
// subModelAction: function(model, subModel){
// model.id; // => the id from the route
// subModel.id // => the subId from the route
// },
//
// // You must provide this method, to create a new
// // model instance and set the id (if provided).
// getModelTypes: function(){
// // return multiple types for multiple ids,
// // based on position in the route definition
// return [App.Pools.Pool, App.Liners.Liner];
// // or just return one, for a single id
// // return App.Pools.Poo;
// }
// });
// ```
Backbone.ModelRouter = (function(Backbone, $, _){
"use strict";
var Router = Backbone.Router.extend({
constructor: function(options){
this._setupModelRoutes();
var args = Array.prototype.slice.call(arguments);
Backbone.Router.prototype.constructor.apply(this, args);
},
// parses the `modelRoutes` and sets up the model fetch
// for each route, callign the specified callback method
// after the model has been fetched
_setupModelRoutes: function(){
var route, routesLength, methodName, resolvedMethodName;
var routes = [],
modelRoutes = Marionette.getOption(this, "modelRoutes");
// order the routes properly in an array
for(route in modelRoutes){
if (modelRoutes.hasOwnProperty(route)){
routes.unshift([route, modelRoutes[route]]);
}
}
// iterate the routes, build the method for the route
// and then set up the route for that method
routesLength = routes.length;
for (var i = 0; i < routesLength; i++){
route = routes[i][0];
methodName = routes[i][1];
resolvedMethodName = "_resolved_" + methodName;
if (this.defineRouteMethod){
this.defineRouteMethod(methodName);
}
this._buildStep(methodName, resolvedMethodName);
this._buildRoute(route, methodName, resolvedMethodName);
}
},
// build the route for the entity loading and callback
_buildRoute: function(route, methodName, resolvedMethodName){
var that = this;
var method = function(){
var args = Array.prototype.slice.call(arguments);
that[resolvedMethodName].apply(that, args);
}
this.route(route, methodName, method);
},
// build the function that loads the entity and then
// runs the specified method from the route
_buildStep: function(methodName, resolvedMethodName){
var that = this;
this[resolvedMethodName] = function(){
var idList = Array.prototype.slice.call(arguments);
var length = idList.length;
var promises = [];
var id;
if (length > 0){
for (var i=0; i<length; i++){
id = idList[i];
promises.push(that._loadEntity(id, i));
}
} else {
promises.push(that._loadEntity());
}
$.when.apply($, promises).then(function(){
var args = Array.prototype.slice.call(arguments);
that[methodName].apply(that, args);
});
};
},
// load the entity and call fetch on it. when it is
// done fetching, resolve the promise so that the
// router methods can be called
_loadEntity: function(id, index){
var self = this;
var promise = $.Deferred();
// get the model types to load, based on index
var ModelTypes = this.getModelTypes();
var ModelType;
if (_.isArray(ModelTypes)){
ModelType = ModelTypes[index];
} else {
ModelType = ModelTypes;
}
// set up the model with the specified id
var model = new ModelType({id: id});
// if we had an id parameter, load up the
// model for that id, and then resolve the promise.
// otherwise, just resolve the promise and move on
if (!model.isNew()){
model.fetch({
success: function(){
promise.resolve(model);
}
});
} else {
promise.resolve(model);
}
return promise.promise();
}
});
return Router;
})(Backbone, jQuery, _);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment