(function() { var Collection, Instance, Singleton, singularize, underscore; var __hasProp = Object.prototype.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; }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; if (typeof Spine === "undefined" || Spine === null) { Spine = require('spine'); } if (typeof require === "undefined" || require === null) { require = (function(value) { return eval(value); }); } Collection = (function() { __extends(Collection, Spine.Module); function Collection(options) { var key, value; if (options == null) { options = {}; } for (key in options) { value = options[key]; this[key] = value; } } Collection.prototype.all = function() { return this.model.select(__bind(function(rec) { return this.associated(rec); }, this)); }; Collection.prototype.first = function() { return this.all()[0]; }; Collection.prototype.last = function() { var values; values = this.all(); return values[values.length - 1]; }; Collection.prototype.find = function(id) { var records; records = this.model.select(__bind(function(rec) { return this.associated(rec) && rec.id === id; }, this)); if (!records[0]) { throw 'Unknown record'; } return records[0]; }; Collection.prototype.select = function(cb) { return this.model.select(__bind(function(rec) { return this.associated(rec) && cb(rec); }, this)); }; Collection.prototype.refresh = function(values) { var record, records, value, _i, _j, _len, _len2; records = this.all(); for (_i = 0, _len = records.length; _i < _len; _i++) { record = records[_i]; delete this.model.records[record.id]; } values = this.model.fromJSON(values); for (_j = 0, _len2 = values.length; _j < _len2; _j++) { value = values[_j]; value.newRecord = false; value[this.fkey] = this.record.id; this.model.records[value.id] = value; } return this.model.trigger('refresh'); }; Collection.prototype.create = function(record) { record[this.fkey] = this.record.id; return this.model.create(record); }; Collection.prototype.associated = function(record) { return record[this.fkey] === this.record.id; }; return Collection; })(); Instance = (function() { __extends(Instance, Spine.Module); 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) { return this.record[this.fkey] = value && value.id; }; return Instance; })(); Singleton = (function() { __extends(Singleton, Spine.Module); 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 != null) { value[this.fkey] = this.id; } return value; }; return Singleton; })(); 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(); }; Spine.Model.extend({ hasMany: function(name, model, fkey) { var association; if (fkey == null) { fkey = "" + (underscore(this.className)) + "_id"; } association = function(record) { if (typeof model === 'string') { model = require(model); } return new Collection({ name: name, model: model, record: record, fkey: fkey }); }; return this.prototype[name] = function(value) { if (value != null) { association(this).refresh(value); } return association(this); }; }, belongsTo: function(name, model, fkey) { var association; if (fkey == null) { fkey = "" + (singularize(name)) + "_id"; } association = function(record) { if (typeof model === 'string') { model = require(model); } 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(name, model, fkey) { var association; if (fkey == null) { fkey = "" + (underscore(this.className)) + "_id"; } association = function(record) { if (typeof model === 'string') { model = require(model); } 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(); }; } }); }).call(this);