UNPKG

rendr

Version:

Render your Backbone.js apps on the client and the server.

139 lines (118 loc) 3.79 kB
/** * Since we make rendr files AMD friendly on app setup stage * we need to pretend that this code is pure commonjs * means no AMD-style require calls. */ var BaseModel = require("./base/model"), BaseCollection = require("./base/collection"); var typePath = { model: "app/models/", collection: "app/collections/" }; module.exports = ModelUtils; function ModelUtils(entryPath) { this.entryPath = entryPath; this._classMap = {}; } ModelUtils.prototype.getModel = function(path, attrs, options, callback) { var Model; attrs = attrs || {}; options = options || {}; if (typeof callback == 'function') { this.getModelConstructor(path, function(Model) { callback(new Model(attrs, options)); }); } else { Model = this.getModelConstructor(path); return new Model(attrs, options); } }; ModelUtils.prototype.getCollection = function(path, models, options, callback) { var Collection; models = models || []; options = options || {}; if (typeof callback == 'function') { this.getCollectionConstructor(path, function(Collection) { callback(new Collection(models, options)); }); } else { Collection = this.getCollectionConstructor(path); return new Collection(models, options); } }; ModelUtils.prototype.getModelConstructor = function(path, callback) { return this.fetchConstructor('model', path, callback); }; ModelUtils.prototype.getCollectionConstructor = function(path, callback) { return this.fetchConstructor('collection', path, callback); }; ModelUtils.prototype.getFullPath = function(type, path) { return this.entryPath + typePath[type] + path; }; ModelUtils.prototype.fetchConstructor = function(type, path, callback) { path = this.underscorize(path); var fullPath = this.getFullPath(type, path); if (this._classMap[path]) { return (typeof callback == 'function') ? callback(this._classMap[path]) : this._classMap[path]; } else if (typeof callback == 'function') { // Only used in AMD environment if (typeof define != 'undefined') { this._requireAMD([fullPath], callback); } else { callback(this._require(fullPath)); } return; } else { return this._require(fullPath); } }; ModelUtils.prototype._require = require; ModelUtils.prototype._requireAMD = require; ModelUtils.prototype.isModel = function(obj) { return obj instanceof BaseModel; }; ModelUtils.prototype.isCollection = function(obj) { return obj instanceof BaseCollection; }; ModelUtils.prototype.getModelNameForCollectionName = function(collectionName) { var Collection; Collection = this.getCollectionConstructor(collectionName); return this.modelName(Collection.prototype.model); }; ModelUtils.uppercaseRe = /([A-Z])/g; ModelUtils.prototype.underscorize = function(name) { if (name == null) { return undefined; } name = name.replace(ModelUtils.uppercaseRe, function(c) { return "_" + c.toLowerCase(); }); if (name[0] === "_") { name = name.slice(1); } return name; }; /** * The 'name' property is added to the constructor when using a named function, * and it cannot be changed. I.e.: * * function MyClass(){} * MyClass.name * -> "MyClass" * * We first look for the 'id' property of the constructor, which is compatible * with standard Backbone-style class inheritance. * * var MyClass = Backbone.Model.extend({}); * MyClass.name * -> "" * MyClass.id = "MyClass" */ ModelUtils.prototype.modelName = function(modelOrCollectionClass) { return this.underscorize(modelOrCollectionClass.id || modelOrCollectionClass.name); }; ModelUtils.prototype.modelIdAttribute = function(modelName, callback) { this.getModelConstructor(modelName, function(constructor) { callback(constructor.prototype.idAttribute); }); };