Permalink
Browse files

Model classes are instances of their own class and get prototypal inh…

…eritance.
  • Loading branch information...
1 parent e551c89 commit 2a21f8c8ffcb6e8cde2bcb46ef94ab6aeb0808df @benpickles committed May 6, 2011
View
@@ -29,18 +29,16 @@ def bundled
def files
@files ||= %w(
model
+ model_utils
model_callbacks
- model_class_methods
model_errors
- model_instance_methods
+ model_instance
+ model_klass
model_local_storage
model_log
- model_module
model_rest
model_uid
- model_utils
model_version
- model_base
)
end
View
@@ -1,27 +1,27 @@
var Model = function(name, func) {
- // The model constructor.
- var model = function(attributes) {
+ var Instance = function(attributes) {
this.attributes = Model.Utils.extend({}, attributes)
- this.changes = {};
- this.errors = new Model.Errors(this);
+ this.changes = {}
+ this.errors = new Model.Errors(this)
this.uid = [name, Model.UID.generate()].join("-")
- if (Model.Utils.isFunction(this.initialize)) this.initialize()
- };
+ }
- // Use module functionality to extend itself onto the constructor. Meta!
- Model.Module.extend.call(model, Model.Module)
+ Instance.prototype = new Model.Instance
+ Instance.prototype.constructor = Instance
- model._name = name
- model.collection = []
- model.unique_key = "id"
- model
- .extend(Model.Callbacks)
- .extend(Model.ClassMethods)
+ var Klass = function(collection) {
+ this.collection = collection || []
+ }
- model.prototype = new Model.Base
- model.prototype.constructor = model
+ Klass.prototype = new Model.Klass
+ Klass.prototype.constructor = Klass
+ Klass.prototype._instance = Instance
+ Klass.prototype._name = name
- if (Model.Utils.isFunction(func)) func.call(model, model, model.prototype)
+ var klass = new Klass()
- return model;
+ if (Model.Utils.isFunction(func))
+ func.call(klass, Klass.prototype, Instance.prototype)
+
+ return klass
};
View
@@ -1,5 +0,0 @@
-Model.Base = (function() {
- function Base() {}
- Base.prototype = Model.Utils.extend({}, Model.Callbacks, Model.InstanceMethods)
- return Base
-})();
@@ -1,4 +1,6 @@
-Model.InstanceMethods = {
+Model.Instance = function() {}
+
+Model.Instance.prototype = {
asJSON: function() {
return this.attr()
},
@@ -32,13 +34,14 @@ Model.InstanceMethods = {
callPersistMethod: function(method, callback) {
var self = this;
+ var klass = this._klass
// Automatically manage adding and removing from the model's Collection.
var manageCollection = function() {
if (method === "destroy") {
- self.constructor.remove(self)
+ klass.remove(self)
} else {
- self.constructor.add(self)
+ klass.add(self)
}
};
@@ -69,8 +72,8 @@ Model.InstanceMethods = {
return value;
};
- if (this.constructor._persistence) {
- this.constructor._persistence[method](this, wrappedCallback);
+ if (klass._persistence) {
+ klass._persistence[method](this, wrappedCallback);
} else {
wrappedCallback.call(this, true);
}
@@ -82,7 +85,7 @@ Model.InstanceMethods = {
},
id: function() {
- return this.attributes[this.constructor.unique_key];
+ return this.attributes[this._klass.unique_key];
},
merge: function(attributes) {
@@ -121,3 +124,5 @@ Model.InstanceMethods = {
return this;
}
};
+
+Model.Utils.extend(Model.Instance.prototype, Model.Callbacks)
@@ -1,4 +1,8 @@
-Model.ClassMethods = {
+Model.Klass = function() {}
+
+Model.Klass.prototype = {
+ unique_key: "id",
+
add: function(model) {
var id = model.id()
@@ -16,7 +20,7 @@ Model.ClassMethods = {
// Convenience method to allow a simple method of chaining class methods.
chain: function(collection) {
- return Model.Utils.extend({}, this, { collection: collection })
+ return new this.constructor(collection)
},
count: function() {
@@ -43,6 +47,11 @@ Model.ClassMethods = {
return this;
},
+ extend: function(obj) {
+ Model.Utils.extend(this.constructor.prototype, obj)
+ return this
+ },
+
find: function(id) {
return this.detect(function() {
return this.id() == id;
@@ -53,6 +62,18 @@ Model.ClassMethods = {
return this.all()[0]
},
+ include: function(obj) {
+ Model.Utils.extend(this._instance.prototype, obj)
+ return this
+ },
+
+ instance: function(attributes) {
+ var instance = new this._instance(attributes)
+ instance._klass = this
+ if (Model.Utils.isFunction(instance.initialize)) instance.initialize()
+ return instance
+ },
+
load: function(callback) {
if (this._persistence) {
var self = this
@@ -175,3 +196,5 @@ Model.ClassMethods = {
return this
}
};
+
+Model.Utils.extend(Model.Klass.prototype, Model.Callbacks)
@@ -74,7 +74,7 @@ Model.localStorage = function(klass) {
if (Model.Utils.inArray(existing_uids, uid) == -1) {
attributes = JSON.parse(localStorage[uid])
- model = new klass(attributes)
+ model = new klass._instance(attributes)
model.uid = uid
models.push(model)
}
View
@@ -1,11 +0,0 @@
-Model.Module = {
- extend: function(obj) {
- Model.Utils.extend(this, obj)
- return this
- },
-
- include: function(obj) {
- Model.Utils.extend(this.prototype, obj)
- return this
- }
-};
View
@@ -40,9 +40,9 @@ Model.REST = function(klass, resource, methods) {
var params;
if (model) {
var attributes = model.asJSON()
- delete attributes[model.constructor.unique_key];
+ delete attributes[model._klass.unique_key];
params = {};
- params[model.constructor._name.toLowerCase()] = attributes;
+ params[model._klass._name.toLowerCase()] = attributes;
} else {
params = null;
}
@@ -58,7 +58,7 @@ Model.REST = function(klass, resource, methods) {
var models = []
for (var i = 0, length = data.length; i < length; i++) {
- models.push(new klass(data[i]))
+ models.push(new klass._instance(data[i]))
}
callback(models)
@@ -1,18 +1,34 @@
module("Model inheritance")
-test("methods added to Model.Base after an instance has been defined", function() {
+test("methods added to Klass after declaration can be called", function() {
var Post = Model("post")
- var post = new Post({ title: "upper" })
+
+ ok(Post.hello === undefined)
+
+ Model.Klass.prototype.hello = function() {
+ return "hello"
+ }
+
+ equal("hello", Post.hello())
+
+ delete Model.Klass.prototype.hello
+
+ ok(Post.hello === undefined)
+})
+
+test("methods added to Instance after an instance has been defined can be called", function() {
+ var Post = Model("post")
+ var post = Post.instance({ title: "upper" })
ok(post.attrUpper === undefined)
- Model.Base.prototype.attrUpper = function(attr) {
+ Model.Instance.prototype.attrUpper = function(attr) {
return this.attr(attr).toUpperCase()
}
equal("UPPER", post.attrUpper("title"))
- delete Model.Base.prototype.attrUpper
+ delete Model.Instance.prototype.attrUpper
ok(post.attrUpper === undefined)
})
Oops, something went wrong.

0 comments on commit 2a21f8c

Please sign in to comment.