Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Pull in fix to preserve model collection #1

Closed
wants to merge 2 commits into from

2 participants

This page is out of date. Refresh to see the latest.
Showing with 13 additions and 3 deletions.
  1. +6 −2 supermodel.js
  2. +1 −1  supermodel.min.js
  3. +6 −0 test/model.js
View
8 supermodel.js
@@ -92,7 +92,7 @@
var One = function(model, options) {
this.required(options, 'inverse', 'model');
Association.apply(this, arguments);
- _.extend(this, _.pick(options, 'inverse', 'model'));
+ _.extend(this, _.pick(options, 'id', 'inverse', 'model'));
_.defaults(this, {
id: this.name + '_id'
});
@@ -443,7 +443,11 @@
// Add the model to `all` for each constructor in its prototype chain.
var ctor = this.constructor;
- do { ctor.all().add(this); } while (ctor = ctor.parent);
+ do {
+ var collection = this.collection;
+ ctor.all().add(this);
+ this.collection = collection;
+ } while (ctor = ctor.parent);
// Trigger 'initialize' for listening associations.
this.trigger('initialize', this);
View
2  supermodel.min.js
@@ -1 +1 @@
-(function(a){var b=this,c=b.Supermodel={};c.VERSION="0.0.4";var d=a.Collection,e=a.Model.extend,f=function(a,b){this.required(b,"name"),_.extend(this,_.pick(b,"name","where","source","store")),_.defaults(this,{source:this.name,store:"_"+this.name});var c=a;do{if(!c.associations()[this.name])continue;throw new Error("Association already exists: "+this.name)}while(c=c.parent);a.associations()[this.name]=this,this.initialize&&a.all().on("initialize",this.initialize,this),this.change&&a.all().on("change",this.change,this),this.parse&&a.all().on("parse",this.parse,this),this.destroy&&a.all().on("destroy",this.destroy,this),this.create&&a.all().on("add",this.create,this)};f.extend=e,_.extend(f.prototype,{associate:function(a,b){if(!this.inverse)return;a.trigger("associate:"+this.inverse,a,b)},dissociate:function(a,b){if(!this.inverse)return;a.trigger("dissociate:"+this.inverse,a,b)},required:function(a){var b;for(var c=1;c<arguments.length;c++){if(a[b=arguments[c]])continue;throw new Error("Option required: "+b)}},andThis:function(a){var b=this;return function(){return a.apply(b,[this].concat(_.toArray(arguments)))}}});var g=f.extend({constructor:function(a,b){this.required(b,"inverse","model"),f.apply(this,arguments),_.extend(this,_.pick(b,"inverse","model")),_.defaults(this,{id:this.name+"_id"}),a.all().on("associate:"+this.name,this.replace,this).on("dissociate:"+this.name,this.remove,this)},create:function(a){a[this.name]=_.bind(this.access,this,a)},access:function(a,b){if(arguments.length<2)return a[this.store];this.replace(a,b)},initialize:function(a){this.parse(a,a.attributes);var b=a.get(this.id);b!=null&&this.replace(a,b)},parse:function(a,b){if(!_.has(b,this.source))return;var c=b[this.source];delete b[this.source],this.replace(a,c)},change:function(a){if(!a.hasChanged(this.id))return;this.replace(a,a.get(this.id))},remove:function(a){this.replace(a,null)},destroy:function(a){var b=a[this.store];if(!b)return;this.remove(a),this.dissociate(b,a)},replace:function(a,b){var c,d;if(!a)return;d=a[this.store],b!=null&&!_.isObject(b)&&(c=b,(b={})[this.model.prototype.idAttribute]=c),b&&!(b instanceof k)&&(b=this.model.create(b));if(d===b)return;b||a.unset(this.id),d&&(delete a[this.store],this.dissociate(d,a));if(!b)return;a.set(this.id,b.id),a[this.store]=b,this.associate(b,a)}}),h=f.extend({constructor:function(a,b){this.required(b,"inverse","collection"),f.apply(this,arguments),_.extend(this,_.pick(b,"collection","inverse")),a.all().on("associate:"+this.name,this._associate,this).on("dissociate:"+this.name,this._dissociate,this)},create:function(a){a[this.name]||(a[this.name]=_.bind(this.get,this,a))},get:function(a){var b=a[this.store];return b?b:(b=a[this.store]=(new this.collection).on("add",this.add,this).on("remove",this.remove,this).on("reset",this.reset,this),b.owner=a,b)},parse:function(a,b){var c=b[this.source];if(!c)return;delete b[this.source];var d=this.get(a);c=d.parse(c);if(!this.where){d.reset(c);return}d.reset(_.filter(_.map(c,function(a){return new d.model(a)}),this.where))},initialize:function(a){this.parse(a,a.attributes)},add:function(a,b){if(!a||!b)return;this.associate(a,b.owner)},remove:function(a,b){if(!a||!b)return;this.dissociate(a,b.owner)},reset:function(a){if(!a)return;a.each(function(b){this.associate(b,a.owner)},this)},destroy:function(a){var b;if(!a||!(b=a[this.store]))return;b.each(function(b){this.dissociate(b,a)},this)},_associate:function(a,b){if(!a||!b)return;if(this.where&&!this.where(b))return;this.get(a).add(b)},_dissociate:function(a,b){if(!a||!b||!a[this.store])return;a[this.store].remove(b)}}),i=f.extend({constructor:function(a,b){this.required(b,"collection","through","source"),f.apply(this,arguments),_.extend(this,_.pick(b,"collection","through")),this._associate=this.andThis(this._associate),this._dissociate=this.andThis(this._dissociate)},create:function(a){a[this.name]||(a[this.name]=_.bind(this.get,this,a))},get:function(a){var b=a[this.store];return b?b:(b=new this.collection,b.owner=a,a[this.store]=b,this.reset(a[this.through]().on("add",this.add,this).on("remove",this.remove,this).on("reset",this.reset,this).on("associate:"+this.source,this._associate).on("dissociate:"+this.source,this._dissociate)),b)},add:function(a,b){if(!a||!b||!(a=a[this.source]()))return;if(this.where&&!this.where(a))return;b.owner[this.name]().add(a)},remove:function(a,b){if(!a||!b||!(a=a[this.source]()))return;var c=b.any(function(b){return b[this.source]()===a},this);c||b.owner[this.name]().remove(a)},reset:function(a){if(!a)return;var b=_.compact(_.uniq(_.invoke(a.models,this.source)));this.where&&(b=_.filter(b,this.where)),a.owner[this.name]().reset(b)},_associate:function(a,b,c){if(!a||!b||!c)return;if(this.where&&!this.where(c))return;a.owner[this.name]().add(c)},_dissociate:function(a,b,c){if(!a||!b||!c)return;var d=a.any(function(a){return a[this.source]()===c},this);d||a.owner[this.name]().remove(c)}}),j=function(a){this.model=a};_.extend(j.prototype,{one:function(a,b){return b.name=a,new g(this.model,b),this},many:function(a,b){b.name=a;var c=b.through?i:h;return new c(this.model,b),this}});var k=c.Model=a.Model.extend({cidAttribute:"cid",initialize:function(){this.set(this.cidAttribute,this.cid);var a=this.constructor;do a.all().add(this);while(a=a.parent);this.trigger("initialize",this)},toJSON:function(){var b=a.Model.prototype.toJSON.apply(this,arguments);return delete b[this.cidAttribute],b},parse:function(a){return this.trigger("parse",this,a),a}},{create:function(a,b){var c,d=this.all(),e=a&&a[this.prototype.cidAttribute],f=a&&a[this.prototype.idAttribute];if(e&&(c=d.getByCid(e))&&c.attributes===a)return c;if(f&&(c=d.get(f)))return c.parse(a),c.set(a),c;if(!f)return new this(a,b);var g=this;do{if(!g.all().get(f))continue;throw new Error('Model with id "'+f+'" already exists.')}while(g=g.parent);return new this(a,b)},has:function(){return new j(this)},all:function(){return this._all||(this._all=new d)},associations:function(){return this._associations||(this._associations={})},reset:function(){this._all=new d,this._associations={}}})}).call(this,Backbone);
+(function(){var e;typeof exports=="undefined"?e=this.Supermodel={}:e=exports,e.VERSION="0.0.4";var t=this._;!t&&typeof require!="undefined"&&(t=require("underscore"));var n=this.Backbone;!n&&typeof require!="undefined"&&(n=require("backbone"));var r=function(e,n){this.required(n,"name"),t.extend(this,t.pick(n,"name","where","source","store")),t.defaults(this,{source:this.name,store:"_"+this.name});var r=e;do{if(!r.associations()[this.name])continue;throw new Error("Association already exists: "+this.name)}while(r=r.parent);e.associations()[this.name]=this,this.initialize&&e.all().on("initialize",this.initialize,this),this.change&&e.all().on("change",this.change,this),this.parse&&e.all().on("parse",this.parse,this),this.destroy&&e.all().on("destroy",this.destroy,this),this.create&&e.all().on("add",this.create,this)};t.extend(r.prototype,{associate:function(e,t){if(!this.inverse)return;e.trigger("associate:"+this.inverse,e,t)},dissociate:function(e,t){if(!this.inverse)return;e.trigger("dissociate:"+this.inverse,e,t)},required:function(e){var t;for(var n=1;n<arguments.length;n++){if(e[t=arguments[n]])continue;throw new Error("Option required: "+t)}},andThis:function(e){var n=this;return function(){return e.apply(n,[this].concat(t.toArray(arguments)))}}});var i=function(e,n){this.required(n,"inverse","model"),r.apply(this,arguments),t.extend(this,t.pick(n,"inverse","model")),t.defaults(this,{id:this.name+"_id"}),e.all().on("associate:"+this.name,this.replace,this).on("dissociate:"+this.name,this.remove,this)};t.extend(i.prototype,r.prototype,{create:function(e){e[this.name]=t.bind(this.access,this,e)},access:function(e,t){if(arguments.length<2)return e[this.store];this.replace(e,t)},initialize:function(e){this.parse(e,e.attributes);var t=e.get(this.id);t!=null&&this.replace(e,t)},parse:function(e,n){if(!n||!t.has(n,this.source))return;var r=n[this.source];delete n[this.source],this.replace(e,r)},change:function(e){if(!e.hasChanged(this.id))return;this.replace(e,e.get(this.id))},remove:function(e){this.replace(e,null)},destroy:function(e){var t=e[this.store];if(!t)return;this.remove(e),this.dissociate(t,e)},replace:function(e,n){var r,i;if(!e)return;i=e[this.store],n!=null&&!t.isObject(n)&&(r=n,(n={})[this.model.prototype.idAttribute]=r),n&&!(n instanceof a)&&(n=this.model.create(n));if(i===n)return;n||e.unset(this.id),i&&(delete e[this.store],this.dissociate(i,e));if(!n)return;e.set(this.id,n.id),e[this.store]=n,this.associate(n,e)}});var s=function(e,n){this.required(n,"inverse","collection"),r.apply(this,arguments),t.extend(this,t.pick(n,"collection","inverse")),e.all().on("associate:"+this.name,this._associate,this).on("dissociate:"+this.name,this._dissociate,this)};t.extend(s.prototype,r.prototype,{create:function(e){e[this.name]||(e[this.name]=t.bind(this.get,this,e))},get:function(e){var t=e[this.store];return t?t:(t=e[this.store]=(new this.collection).on("add",this.add,this).on("remove",this.remove,this).on("reset",this.reset,this),t.owner=e,t)},parse:function(e,n){if(!n)return;var r=n[this.source];if(!r)return;delete n[this.source];var i=this.get(e);r=i.parse(r);if(!this.where){i.reset(r);return}i.reset(t.filter(t.map(r,function(e){return new i.model(e)}),this.where))},initialize:function(e){this.parse(e,e.attributes)},add:function(e,t){if(!e||!t)return;this.associate(e,t.owner)},remove:function(e,t){if(!e||!t)return;this.dissociate(e,t.owner)},reset:function(e){if(!e)return;e.each(function(t){this.associate(t,e.owner)},this)},destroy:function(e){var t;if(!e||!(t=e[this.store]))return;t.each(function(t){this.dissociate(t,e)},this)},_associate:function(e,t){if(!e||!t)return;if(this.where&&!this.where(t))return;this.get(e).add(t)},_dissociate:function(e,t){if(!e||!t||!e[this.store])return;e[this.store].remove(t)}});var o=function(e,n){this.required(n,"collection","through","source"),r.apply(this,arguments),t.extend(this,t.pick(n,"collection","through")),this._associate=this.andThis(this._associate),this._dissociate=this.andThis(this._dissociate)};t.extend(o.prototype,r.prototype,{create:function(e){e[this.name]||(e[this.name]=t.bind(this.get,this,e))},get:function(e){var t=e[this.store];return t?t:(t=new this.collection,t.owner=e,e[this.store]=t,this.reset(e[this.through]().on("add",this.add,this).on("remove",this.remove,this).on("reset",this.reset,this).on("associate:"+this.source,this._associate).on("dissociate:"+this.source,this._dissociate)),t)},add:function(e,t){if(!e||!t||!(e=e[this.source]()))return;if(this.where&&!this.where(e))return;t.owner[this.name]().add(e)},remove:function(e,t){if(!e||!t||!(e=e[this.source]()))return;var n=t.any(function(t){return t[this.source]()===e},this);n||t.owner[this.name]().remove(e)},reset:function(e){if(!e)return;var n=t.compact(t.uniq(t.invoke(e.models,this.source)));this.where&&(n=t.filter(n,this.where)),e.owner[this.name]().reset(n)},_associate:function(e,t,n){if(!e||!t||!n)return;if(this.where&&!this.where(n))return;e.owner[this.name]().add(n)},_dissociate:function(e,t,n){if(!e||!t||!n)return;var r=e.any(function(e){return e[this.source]()===n},this);r||e.owner[this.name]().remove(n)}});var u=function(e){this.model=e};t.extend(u.prototype,{one:function(e,t){return t.name=e,new i(this.model,t),this},many:function(e,t){t.name=e;var n=t.through?o:s;return new n(this.model,t),this}});var a=e.Model=n.Model.extend({cidAttribute:"cid",initialize:function(){this.set(this.cidAttribute,this.cid);var e=this.constructor;do{var t=this.collection;e.all().add(this),this.collection=t}while(e=e.parent);this.trigger("initialize",this)},toJSON:function(){var e=n.Model.prototype.toJSON.apply(this,arguments);return delete e[this.cidAttribute],e},parse:function(e){return this.trigger("parse",this,e),e}},{create:function(e,t){var n,r=this.all(),i=e&&e[this.prototype.cidAttribute],s=e&&e[this.prototype.idAttribute];if(i&&(n=r.getByCid(i))&&n.attributes===e)return n;if(s&&(n=r.get(s)))return n.parse(e),n.set(e),n;if(!s)return new this(e,t);var o=this;do{if(!o.all().get(s))continue;throw new Error('Model with id "'+s+'" already exists.')}while(o=o.parent);return new this(e,t)},has:function(){return new u(this)},all:function(){return this._all||(this._all=new n.Collection)},associations:function(){return this._associations||(this._associations={})},reset:function(){this._all=new n.Collection,this._associations={}}})}).call(this);
View
6 test/model.js
@@ -66,6 +66,12 @@
ok(Model.create({cid: model.cid}) !== model);
});
+ test('Model creation doesn\'t set the model collection as the all collection.', function() {
+ var Model = Supermodel.Model.extend();
+ var model = Model.create();
+ ok(model.collection === undefined);
+ });
+
test('Use cidAttribute to identify attributes.', function() {
var Model = Supermodel.Model.extend({cidAttribute: '_cid'});
var model = Model.create();
Something went wrong with that request. Please try again.