Skip to content

Instantly share code, notes, and snippets.

@j-manu
Forked from jpallen/gist:2762417
Created May 21, 2012 14:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save j-manu/2762570 to your computer and use it in GitHub Desktop.
Save j-manu/2762570 to your computer and use it in GitHub Desktop.
Add a .findOrBuild() method to Backbone Models
// keep models fetched in different views in sync
// Finding and creating models
// ===========================
//
// We might need to get a reference to a model from anywhere in our code
// and we want to make sure that these references all point to the same model.
// Otherwise updates to one copy of the model won't affect another.
//
// The methods here let you get models through a wrapper that will either
// create the model if it doesn't exist anywhere, or return a reference to
// the existing model. E.g.
//
// var Train = ModelWithFind.extend();
// var thomas = Train.findOrBuild("thomas");
// thomas == Train.findOrBuild("thomas"); // true
// thomas == new Train({ "id" : "thomas" }); // false
//
// Models are looked up by their `id`. If the model doesn't exist yet then it
// is created and the attribute given by `idAttribute` is set to the passed value.
var ModelWithFind = Backbone.Model.extend({}, {
// When trying to get a reference to a model, you should use `findOrBuild`.
// This takes one argument which is the model's `id` and will either return the
// existing model with that `id` or create it if it doesn't exist.
findOrBuild : function(id) {
var model = this.find(id);
if (model) return model;
var options = {};
options[this.prototype.idAttribute] = id;
return this.build(options);
},
// `build` is a wrapper for the usual `new Model()`. It instantiates the model
// but then saves it in the index of loaded models.
build : function(options) {
var model = new this(options);
this.loadedModels = this.loadedModels || {};
this.loadedModels[model.id] = model;
// It's possible for a model's id to change. If it does we update our index.
var self = this;
model.on("change:" + model.idAttribute, function() {
self.loadedModels[model.id] = self.loadedModels[model.previous(model.idAttribute)]
delete self.loadedModels[model.previous(model.idAttribute)];
})
return model;
},
// `find` looks up a model in the index and returns it if it's present.
find : function(id) {
this.loadedModels = this.loadedModels || {};
return this.loadedModels[id];
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment