micromodel
Version:
Model that can be used on both Client & Server
308 lines (275 loc) • 8.05 kB
JavaScript
// Generated by CoffeeScript 1.8.0
(function() {
var Model, defineClassInheritableAccessor, _,
__hasProp = {}.hasOwnProperty,
__slice = [].slice;
if (typeof _ === "undefined" || _ === null) {
_ = require('underscore');
}
defineClassInheritableAccessor = function(obj, name, defaultValue) {
var _name;
_name = "_" + name;
return obj[name] = function() {
var _ref;
if (this[_name] == null) {
this[_name] = _(defaultValue).clone();
}
if (this[_name] === ((_ref = this.__super__) != null ? _ref.constructor[_name] : void 0)) {
this[_name] = _(this[_name]).clone();
}
return this[_name];
};
};
Model = (function() {
var attributeRe;
attributeRe = /^_|^errors$/;
Model.prototype.isModel = true;
defineClassInheritableAccessor(Model, '_defaults', {});
Model.defaults = function(attrs) {
var name, value, _results;
if (attrs) {
_results = [];
for (name in attrs) {
value = attrs[name];
_results.push(this._defaults()[name] = value);
}
return _results;
} else {
return this._defaults();
}
};
function Model(attrs, options) {
var defaults;
this.errors = {};
if (!_.isEmpty(defaults = this.constructor.defaults())) {
this.set(_(defaults).clone());
}
if (attrs) {
this.set(attrs, options);
}
this;
}
Model.prototype.isNew = function() {
return this.id != null;
};
Model.prototype.isEqual = function(other) {
var name, otherSize, size, value;
if (this === other) {
return true;
}
if (!(other && this.id === other.id && other.isModel)) {
return false;
}
size = 0;
for (name in this) {
if (!__hasProp.call(this, name)) continue;
value = this[name];
if (!(!attributeRe.test(name))) {
continue;
}
size += 1;
if (!_.isEqual(value, other[name])) {
return false;
}
}
otherSize = 0;
for (name in other) {
if (!__hasProp.call(other, name)) continue;
if (!attributeRe.test(name)) {
otherSize += 1;
}
}
return size === otherSize;
};
Model.prototype.set = function(attrs, options) {
var changes, name, newValue, oldValue;
if (attrs == null) {
return {};
}
if (options && options.cast) {
return this.castAndSet(attrs, options);
}
if (this.parse) {
attrs = this.parse(attrs);
}
changes = {};
for (name in attrs) {
if (!__hasProp.call(attrs, name)) continue;
newValue = attrs[name];
if (!(!attributeRe.test(name))) {
continue;
}
oldValue = this[name];
if (!_.isEqual(oldValue, newValue)) {
changes[name] = oldValue;
}
this[name] = newValue;
}
return changes;
};
Model.prototype.clone = function() {
return new this.constructor(this.attributes());
};
Model.prototype.clear = function(options) {
var changes, name;
changes = attributes();
for (name in this) {
if (!__hasProp.call(this, name)) continue;
delete this[name];
}
return changes;
};
defineClassInheritableAccessor(Model, '_validations', {});
Model.validations = function(validations) {
var name, validator, _results;
if (validations) {
_results = [];
for (name in validations) {
validator = validations[name];
_results.push(this._validations()[name] = validator);
}
return _results;
} else {
return this._validations();
}
};
Model.prototype.validate = function() {
var msg, name, validator, _base, _ref, _results;
_ref = this.constructor.validations();
_results = [];
for (name in _ref) {
if (!__hasProp.call(_ref, name)) continue;
validator = _ref[name];
if (msg = validator.call(this, this[name])) {
_results.push(((_base = this.errors)[name] != null ? _base[name] : _base[name] = []).push(msg));
} else {
_results.push(void 0);
}
}
return _results;
};
Model.prototype.isValid = function() {
this.errors = {};
this.validate();
return _(this.errors).isEmpty();
};
Model.prototype.hasErrors = function() {
return !_(this.errors).isEmpty();
};
Model.prototype.addError = function() {
var args, _base, _base1, _name;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
if (args.length < 2) {
return ((_base = this.errors).base != null ? _base.base : _base.base = []).push(args[0]);
} else {
return ((_base1 = this.errors)[_name = args[0]] != null ? _base1[_name] : _base1[_name] = []).push(args[1]);
}
};
Model.prototype.attributes = function() {
var attrs, name, value;
attrs = {};
for (name in this) {
if (!__hasProp.call(this, name)) continue;
value = this[name];
if (!attributeRe.test(name)) {
attrs[name] = value;
}
}
return attrs;
};
Model.prototype.toJson = function() {
return this.attributes();
};
Model.prototype.toJSON = function() {
var args;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
return this.toJson.apply(this, args);
};
Model.prototype.toString = function() {
return JSON.stringify(this.toJson());
};
Model.generateId = function(length) {
var count, id, rand, symbols, _ref;
if (length == null) {
length = 6;
}
symbols = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
_ref = ["", length + 1], id = _ref[0], count = _ref[1];
while (count -= 1) {
rand = Math.floor(Math.random() * symbols.length);
id += symbols[rand];
}
return id;
};
Model.cast = function(value, type) {
var tmp;
if (_.isFunction(type)) {
return type(value);
} else if (type === String) {
return v.toString();
} else if (type === Number) {
if (_.isNumber(v)) {
return v;
} else if (_.isString(v)) {
tmp = parseInt(v);
if (_.isNumber(tmp)) {
return tmp;
}
}
} else if (type === Boolean) {
if (_.isBoolean(v)) {
return v;
} else if (_.isString(v)) {
return v === 'true';
}
} else if (type === Date) {
if (_.isDate(v)) {
return v;
} else if (_.isString(v)) {
tmp = new Date(v);
if (_.isDate(tmp)) {
return tmp;
}
}
} else {
throw new Error("can't cast to unknown type '" + type + "'!");
}
};
defineClassInheritableAccessor(Model, '_types', {});
Model.types = function(types) {
var name, type, _results;
if (types) {
_results = [];
for (name in types) {
type = types[name];
_results.push(this._types()[name] = type);
}
return _results;
} else {
return this._types();
}
};
Model.prototype.castAndSet = function(attrs, options) {
var casted, name, type, _ref;
casted = {};
_ref = this.constructor.types();
for (name in _ref) {
type = _ref[name];
if (name in attrs) {
casted[name] = Model.cast(attrs[name], type);
}
}
if (options && options.cast) {
options = _(options).clone();
delete options.cast;
}
return this.set(casted, options);
};
return Model;
})();
if ((typeof module !== "undefined" && module !== null ? module.exports : void 0) != null) {
module.exports = Model;
} else {
window.Model = Model;
}
}).call(this);