Created
November 23, 2013 13:54
-
-
Save arendjr/7614865 to your computer and use it in GitHub Desktop.
Laces.js-based Model implementation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Base class for all models. | |
* | |
* @param application Application instance. | |
* @param attributes Optional map of attributes to assign to the model. | |
*/ | |
function Model(application, attributes) { | |
if (!application) { | |
console.log("Model instantiated without Application reference"); | |
} | |
Laces.Model.call(this); | |
/** | |
* Reference to the application object. | |
*/ | |
this.application = application; | |
/** | |
* Whether the model is currently being fetched from the server. | |
*/ | |
this.fetchInProgress = false; | |
this.set(_.extend({ id: null }, this.defaults, attributes)); | |
this._fetchPromise = null; | |
if (this.initialize) { | |
this.initialize(); | |
} | |
} | |
Model.extend = extend; | |
Model.prototype = new Laces.Model(); | |
Model.prototype.constructor = Model; | |
_.extend(Model.prototype, { | |
/** | |
* Object containing default attributes. | |
*/ | |
defaults: {}, | |
/** | |
* Fetches all the model's attributes from the server. | |
* | |
* @param options Optional options object. May contain the following properties: | |
* context - Context in which to execute the promise callbacks. | |
*/ | |
fetch: function(options) { | |
options = options || {}; | |
if (this._fetchPromise) { | |
return this._fetchPromise; | |
} | |
var url = _.result(this, "url"); | |
var self = this; | |
var promise = this.application.api.ajax(url, { context: options.context }); | |
promise.then(function(data) { | |
self.set(data); | |
self._fetchPromise = null; | |
self.fetchInProgress = false; | |
}); | |
this._fetchPromise = promise; | |
this.fetchInProgress = true; | |
return promise; | |
}, | |
/** | |
* Returns whether the model is new, or in other words, hasn't been saved to the server yet. | |
*/ | |
isNew: function() { | |
return !this.id; | |
}, | |
/** | |
* Plural version of the model type. | |
*/ | |
plural: "", | |
/** | |
* Removes the model instance from the server. | |
* | |
* @param options Optional options object. May contain the following properties: | |
* context - Context in which to execute the promise callbacks. | |
*/ | |
remove: function(options) { | |
options = options || {}; | |
var url = _.result(this, "url"); | |
var settings = { | |
context: options.context, | |
type: "DELETE" | |
}; | |
var self = this; | |
var promise = this.application.api.ajax(url, settings); | |
promise.then(function() { | |
self.application.notificationBus.signal("model:removed", self); | |
}); | |
return promise; | |
}, | |
/** | |
* Saves all the model's attributes to the server. | |
* | |
* @param options Optional options object. May contain the following properties: | |
* context - Context in which to execute the promise callbacks. | |
*/ | |
save: function(options) { | |
options = options || {}; | |
var url = _.result(this, "url"); | |
var settings = { | |
contentType: "application/json; charset=UTF-8", | |
context: options.context, | |
data: JSON.stringify(this.toJSON()), | |
dataType: "json", | |
processData: false, | |
type: (this.isNew() ? "POST" : "PUT") | |
}; | |
var self = this; | |
var promise = this.application.api.ajax(url, settings); | |
promise.then(function(data) { | |
if (!self.id) { | |
self.id = data.id; | |
} | |
}); | |
return promise; | |
}, | |
/** | |
* Sets one or more attributes on the model. | |
* | |
* @param key Key of the attribute to set. | |
* @param value Value of the attribute. | |
* | |
* Rather than setting attributes one by one, you can also pass an entire attributes object | |
* instead of the key and value parameters. | |
* | |
* Note that because Model inherits from Laces.Model, any set attributes can also be | |
* accessed directly through dot notation. (And because of this, you should avoid using | |
* attribute names that collide with method names or Model's generic properties.) | |
*/ | |
set: function(key/*, value*/) { | |
if (typeof key === "object") { | |
_.each(key, function(value, key) { | |
Laces.Model.prototype.set.call(this, key, value); | |
}, this); | |
} else { | |
Laces.Model.prototype.set.apply(this, arguments); | |
} | |
}, | |
/** | |
* The model's type. | |
*/ | |
type: "", | |
/** | |
* Converts the model to JSON representation for saving to the server. | |
*/ | |
toJSON: function() { | |
var json = {}; | |
_.each(this.keys(), function(key) { | |
if (key !== "id" || !this.isNew()) { | |
json[key] = this[key]; | |
} | |
}, this); | |
return json; | |
}, | |
/** | |
* Unsets an attribute from the model. | |
* | |
* @param key Key of the attribute to set. | |
*/ | |
unset: function(key) { | |
Laces.Model.prototype.remove.call(this, key); | |
}, | |
/** | |
* Returns the URL from which to fetch and to which to store the model. | |
* | |
* May also be a plain string instead of a method. | |
*/ | |
url: function() { | |
return (this.plural || this.type) + "/" + (this.isNew() ? "" : this.id + "/"); | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment