tiger
Version:
A full port of Spine.js MVC framework to Titanium Mobile, with enhancements
604 lines (536 loc) • 16.8 kB
JavaScript
// Generated by CoffeeScript 1.6.3
(function() {
var BaseCollection, Collection, Instance, M2MCollection, O2MCollection, Relations, Singleton, Tiger, isArray, loadModel, singularize, underscore, _ref, _ref1, _ref2,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
Tiger = this.Tiger || require('./tiger');
isArray = Tiger.isArray;
BaseCollection = (function(_super) {
__extends(BaseCollection, _super);
function BaseCollection(options) {
var key, value;
if (options == null) {
options = {};
}
for (key in options) {
value = options[key];
this[key] = value;
}
}
BaseCollection.prototype.first = function() {
return this.all()[0];
};
BaseCollection.prototype.last = function() {
var values;
values = this.all();
return values[values.length - 1];
};
BaseCollection.prototype.create = function(record) {
var newRecord;
newRecord = this.model.create(record);
if (newRecord) {
return this.add(newRecord);
}
};
return BaseCollection;
})(Tiger.Class);
Collection = (function(_super) {
__extends(Collection, _super);
function Collection() {
_ref = Collection.__super__.constructor.apply(this, arguments);
return _ref;
}
Collection.prototype.add = function(fItem) {
fItem[this.fkey] = this.record.id;
return fItem.save();
};
Collection.prototype.remove = function(fItem) {
if (typeof fItem === 'string') {
fItem = this.find(fItem);
}
return fItem.destroy();
};
Collection.prototype.all = function() {
var _this = this;
return this.model.select(function(rec) {
return _this.associated(rec);
});
};
Collection.prototype.find = function(id) {
var records,
_this = this;
records = this.select(function(rec) {
return rec.id + '' === id + '';
});
if (!records[0]) {
throw 'Unknown record';
}
return records[0];
};
Collection.prototype.findAllByAttribute = function(name, value) {
var _this = this;
return this.model.select(function(rec) {
return _this.associated(rec) && rec[name] === value;
});
};
Collection.prototype.findByAttribute = function(name, value) {
return this.findAllByAttribute(name, value)[0];
};
Collection.prototype.select = function(cb) {
var _this = this;
return this.model.select(function(rec) {
return _this.associated(rec) && cb(rec);
});
};
Collection.prototype.refresh = function(values) {
var record, records, _i, _j, _len, _len1, _ref1;
_ref1 = this.all();
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
record = _ref1[_i];
delete this.model.records[record.id];
}
records = this.model.fromJSON(values);
if (!isArray(records)) {
records = [records];
}
for (_j = 0, _len1 = records.length; _j < _len1; _j++) {
record = records[_j];
record.newRecord = false;
record[this.fkey] = this.record.id;
this.model.records[record.id] = record;
}
return this.model.trigger('refresh', this.model.cloneArray(records));
};
Collection.prototype.associated = function(record) {
return record[this.fkey] === this.record.id;
};
return Collection;
})(BaseCollection);
O2MCollection = (function(_super) {
__extends(O2MCollection, _super);
function O2MCollection() {
_ref1 = O2MCollection.__super__.constructor.apply(this, arguments);
return _ref1;
}
O2MCollection.prototype.add = function(item, save) {
var i, _i, _len;
if (save == null) {
save = true;
}
if (isArray(item)) {
for (_i = 0, _len = item.length; _i < _len; _i++) {
i = item[_i];
this.add(i, false);
}
} else {
if (!(item instanceof this.model)) {
item = this.model.find(item);
}
this.record[this.lkey].push(item[this.fkey]);
}
if (save) {
return this.record.save();
}
};
O2MCollection.prototype.remove = function(item) {
if (!(item instanceof this.model)) {
item = this.model.find(item);
}
this.record[this.lkey].splice(this.record[this.lkey].indexOf(item[this.fkey]), 1);
return this.record.save();
};
O2MCollection.prototype.all = function() {
var lkey, _i, _len, _ref2, _results;
_ref2 = this.record[this.lkey];
_results = [];
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
lkey = _ref2[_i];
_results.push(this.model.find(lkey));
}
return _results;
};
O2MCollection.prototype.find = function(id) {
return __indexOf.call(this.record[this.lkey], id) >= 0 && this.model.find(id || (function() {
throw 'Unknown record';
})());
};
return O2MCollection;
})(BaseCollection);
M2MCollection = (function(_super) {
__extends(M2MCollection, _super);
function M2MCollection() {
_ref2 = M2MCollection.__super__.constructor.apply(this, arguments);
return _ref2;
}
M2MCollection.prototype.add = function(item, save) {
var hub, i, _i, _len;
if (save == null) {
save = true;
}
if (isArray(item)) {
for (_i = 0, _len = item.length; _i < _len; _i++) {
i = item[_i];
this.add(i, false);
}
} else {
if (!(item instanceof this.model)) {
item = this.model.find(item);
}
hub = new this.Hub();
if (this.left_to_right) {
hub["" + this.rev_name + "_id"] = this.record.id;
hub["" + this.name + "_id"] = item.id;
} else {
hub["" + this.rev_name + "_id"] = item.id;
hub["" + this.name + "_id"] = this.record.id;
}
}
if (save) {
return hub.save();
}
};
M2MCollection.prototype.remove = function(item) {
var i, _i, _len, _ref3, _results,
_this = this;
_ref3 = this.Hub.select(function(item) {
return _this.associated(item);
});
_results = [];
for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
i = _ref3[_i];
_results.push(i.destroy());
}
return _results;
};
M2MCollection.prototype._link = function(items) {
var _this = this;
return items.map(function(item) {
if (_this.left_to_right) {
return _this.model.find(item["" + _this.name + "_id"]);
} else {
return _this.model.find(item["" + _this.rev_name + "_id"]);
}
});
};
M2MCollection.prototype.all = function() {
var _this = this;
return this._link(this.Hub.select(function(item) {
return _this.associated(item);
}));
};
M2MCollection.prototype.find = function(id) {
var records,
_this = this;
records = this.Hub.select(function(rec) {
return _this.associated(rec, id);
});
if (!records[0]) {
throw 'Unknown record';
}
return this._link(records)[0];
};
M2MCollection.prototype.associated = function(record, id) {
if (this.left_to_right) {
if (record["" + this.rev_name + "_id"] !== this.record.id) {
return false;
}
if (id) {
return record["" + this.rev_name + "_id"] === id;
}
} else {
if (record["" + this.name + "_id"] !== this.record.id) {
return false;
}
if (id) {
return record["" + this.name + "_id"] === id;
}
}
return true;
};
return M2MCollection;
})(BaseCollection);
Instance = (function(_super) {
__extends(Instance, _super);
function Instance(options) {
var key, value;
if (options == null) {
options = {};
}
for (key in options) {
value = options[key];
this[key] = value;
}
}
Instance.prototype.exists = function() {
return this.record[this.fkey] && this.model.exists(this.record[this.fkey]);
};
Instance.prototype.update = function(value) {
if (!(value instanceof this.model)) {
value = new this.model(value);
}
if (value.isNew()) {
value.save();
}
this.record[this.fkey] = value && value.id;
return this.record.save();
};
return Instance;
})(Tiger.Class);
Singleton = (function(_super) {
__extends(Singleton, _super);
function Singleton(options) {
var key, value;
if (options == null) {
options = {};
}
for (key in options) {
value = options[key];
this[key] = value;
}
}
Singleton.prototype.find = function() {
return this.record.id && this.model.findByAttribute(this.fkey, this.record.id);
};
Singleton.prototype.update = function(value) {
if (!(value instanceof this.model)) {
value = this.model.fromJSON(value);
}
value[this.fkey] = this.record.id;
return value.save();
};
return Singleton;
})(Tiger.Class);
singularize = function(str) {
return str.replace(/s$/, '');
};
underscore = function(str) {
return str.replace(/::/g, '/').replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2').replace(/([a-z\d])([A-Z])/g, '$1_$2').replace(/-/g, '_').toLowerCase();
};
loadModel = function(model, parent) {
var _this = this;
if (typeof model === 'string') {
model = require(model);
model.bind('error', function(record, msg) {
return parent.trigger('error', record, msg, model.className);
});
if (typeof model.loadTigerDB === 'function') {
model.bindTigerDB().fetch();
}
}
return model;
};
Relations = {
__filter: function(args, revert) {
if (revert == null) {
revert = false;
}
return function(rec) {
var key, q, value;
q = !!revert;
for (key in args) {
value = args[key];
if (rec[key] !== value) {
return q;
}
}
return !q;
};
},
filter: function(args) {
return this.select(this.__filter(args));
},
exclude: function(args) {
return this.select(this.__filter(args, true));
},
oneToMany: function(model, name, fkey) {
var association, lkey, parent;
parent = this;
if (name == null) {
model = loadModel(model, parent);
name = model.className.toLowerCase();
name = singularize(underscore(name));
}
lkey = "" + name + "_ids";
if (__indexOf.call(this.attributes, lkey) < 0) {
this.attributes.push(lkey);
}
if (fkey == null) {
fkey = 'id';
}
association = function(record, model) {
model = loadModel(model, parent);
if (!record[lkey]) {
record[lkey] = [];
}
return new O2MCollection({
lkey: lkey,
fkey: fkey,
record: record,
model: model
});
};
return this.prototype["" + name + "s"] = function(value) {
return association(this, model);
};
},
hasMany: function(model, name, fkey) {
var association, parent;
parent = this;
if (name == null) {
model = loadModel(model, parent);
name = model.className.toLowerCase();
name = singularize(underscore(name));
}
if (fkey == null) {
fkey = "" + (underscore(this.className)) + "_id";
}
association = function(record) {
model = loadModel(model, parent);
return new Collection({
name: name,
model: model,
record: record,
fkey: fkey
});
};
return this.prototype["" + name + "s"] = function(value) {
if (value != null) {
association(this).refresh(value);
}
return association(this);
};
},
belongsTo: function(model, name, fkey) {
var association, parent;
parent = this;
if (name == null) {
model = loadModel(model, parent);
name = model.className.toLowerCase();
name = singularize(underscore(name));
}
if (fkey == null) {
fkey = "" + name + "_id";
}
association = function(record) {
model = loadModel(model, parent);
return new Instance({
name: name,
model: model,
record: record,
fkey: fkey
});
};
this.prototype[name] = function(value) {
if (value != null) {
association(this).update(value);
}
return association(this).exists();
};
return this.attributes.push(fkey);
},
hasOne: function(model, name, fkey) {
var association, parent;
parent = this;
if (name == null) {
model = loadModel(model, parent);
name = model.className.toLowerCase();
name = singularize(underscore(name));
}
if (fkey == null) {
fkey = "" + (underscore(this.className)) + "_id";
}
association = function(record) {
model = loadModel(model, parent);
return new Singleton({
name: name,
model: model,
record: record,
fkey: fkey
});
};
return this.prototype[name] = function(value) {
if (value != null) {
association(this).update(value);
}
return association(this).find();
};
},
foreignKey: function(model, name, rev_name) {
var parent;
parent = this;
if (name == null) {
model = loadModel(model, parent);
name = model.className.toLowerCase();
name = singularize(underscore(name));
}
if (rev_name == null) {
rev_name = this.className.toLowerCase();
rev_name = singularize(underscore(rev_name));
rev_name = "" + rev_name + "s";
}
this.belongsTo(name, model);
return model.hasMany(rev_name, this);
},
manyToMany: function(model, name, rev_name) {
var Hub, association, local, parent, rev_model, tigerDB, _ref3;
parent = this;
if (name == null) {
model = loadModel(model, parent);
name = model.className.toLowerCase();
name = singularize(underscore(name));
}
if (rev_name == null) {
rev_name = this.className.toLowerCase();
rev_name = singularize(underscore(rev_name));
rev_name = "" + rev_name + "s";
}
rev_model = this;
local = typeof model.loadLocal === 'function' || typeof rev_model.loadLocal === 'function';
tigerDB = typeof model.loadTigerDB === 'function' || typeof rev_model.loadTigerDB === 'function';
Hub = (function(_super) {
__extends(Hub, _super);
function Hub() {
_ref3 = Hub.__super__.constructor.apply(this, arguments);
return _ref3;
}
if (local) {
Hub.extend(Tiger.Model.Local);
}
if (tigerDB) {
Hub.extend(Tiger.Model.TigerDB);
}
Hub.configure("_" + rev_name + "_to_" + name, "" + Hub.rev_name + "_id", "" + Hub.name + "_id");
return Hub;
})(Tiger.Model);
if (local || tigerDB) {
Hub.fetch();
}
Hub.foreignKey(rev_model, "" + rev_name);
Hub.foreignKey(model, "" + name);
association = function(record, model, left_to_right) {
model = loadModel(model, parent);
return new M2MCollection({
name: name,
rev_name: rev_name,
record: record,
model: model,
Hub: Hub,
left_to_right: left_to_right
});
};
rev_model.prototype["" + name + "s"] = function(value) {
return association(this, model, true);
};
return model.prototype["" + rev_name + "s"] = function(value) {
return association(this, rev_model, false);
};
}
};
Tiger.Model.extend(Relations);
Relations.loadModel = loadModel;
Tiger.Model.Relations = Relations;
if (typeof module !== "undefined" && module !== null) {
module.exports = Relations;
}
}).call(this);