ember-data-source 1.0.0.beta.2 → 1.0.0.beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,15 +1,17 @@
1
1
  // ==========================================================================
2
2
  // Project: Ember Data
3
- // Copyright: ©2011-2012 Tilde Inc. and contributors.
4
- // Portions ©2011 Living Social Inc. and contributors.
3
+ // Copyright: Copyright 2011-2013 Tilde Inc. and contributors.
4
+ // Portions Copyright 2011 LivingSocial Inc.
5
5
  // License: Licensed under MIT license (see license.js)
6
6
  // ==========================================================================
7
7
 
8
8
 
9
9
 
10
- // Version: v1.0.0-beta.2
11
- // Last commit: d1158e2 (2013-09-04 16:03:06 -0700)
10
+ // Version: v1.0.0-beta.3-48-gb47afef
11
+ // Last commit: b47afef (2013-10-08 19:07:59 -0700)
12
12
 
13
13
 
14
- !function(){var e,t;!function(){var r={},n={};e=function(e,t,n){r[e]={deps:t,callback:n}},t=function(e){if(n[e])return n[e];n[e]={};var i,a,o,s,c;if(i=r[e],!i)throw new Error("Module '"+e+"' not found.");a=i.deps,o=i.callback,s=[];for(var d=0,u=a.length;u>d;d++)"exports"===a[d]?s.push(c={}):s.push(t(a[d]));var l=o.apply(this,s);return n[e]=c||l}}(),function(){"undefined"==typeof DS&&(DS=Ember.Namespace.create({VERSION:"1.0.0-beta.1"}),"undefined"!=typeof window&&(window.DS=DS))}(),function(){function e(e){return function(){return this[e].apply(this,arguments)}}var t=Ember.get,r=(Ember.set,Ember.isNone);DS.JSONSerializer=Ember.Object.extend({primaryKey:"id",applyTransforms:function(e,t){return e.eachTransformedAttribute(function(e,r){var n=this.transformFor(r);t[e]=n.deserialize(t[e])},this),t},normalize:function(e,t){return t?(this.applyTransforms(e,t),t):t},serialize:function(e,r){t(this,"store");var n={};if(r&&r.includeId){var i=t(e,"id");i&&(n[t(this,"primaryKey")]=t(e,"id"))}return e.eachAttribute(function(t,r){this.serializeAttribute(e,n,t,r)},this),e.eachRelationship(function(t,r){"belongsTo"===r.kind?this.serializeBelongsTo(e,n,r):"hasMany"===r.kind&&this.serializeHasMany(e,n,r)},this),n},serializeAttribute:function(e,r,n,i){var a=t(this,"attrs"),o=t(e,n),s=i.type;if(s){var c=this.transformFor(s);o=c.serialize(o)}n=a&&a[n]||n,r[n]=o},serializeBelongsTo:function(e,n,i){var a=i.key,o=t(e,a);r(o)||(n[a]=t(o,"id"),i.options.polymorphic&&(n[a+"_type"]=o.constructor.typeKey))},serializeHasMany:function(e,r,n){var i=n.key,a=DS.RelationshipChange.determineRelationshipType(e.constructor,n);("manyToNone"===a||"manyToMany"===a)&&(r[i]=t(e,i).mapBy("id"))},extract:function(e,t,r,n,i){this.extractMeta(e,t,r);var a="extract"+i.charAt(0).toUpperCase()+i.substr(1);return this[a](e,t,r,n,i)},extractFindAll:e("extractArray"),extractFindQuery:e("extractArray"),extractFindMany:e("extractArray"),extractFindHasMany:e("extractArray"),extractCreateRecord:e("extractSave"),extractUpdateRecord:e("extractSave"),extractDeleteRecord:e("extractSave"),extractFind:e("extractSingle"),extractSave:e("extractSingle"),extractSingle:function(e,t,r){return this.normalize(t,r)},extractArray:function(e,t,r){return this.normalize(t,r)},extractMeta:function(e,t,r){r&&r.meta&&(e.metaForType(t,r.meta),delete r.meta)},typeFor:function(e,t,r){return e.options.polymorphic?r[t+"_type"]:e.type},transformFor:function(e){return this.container.lookup("transform:"+e)}})}(),function(){var e=Ember.get,t=Ember.String.capitalize,r=Ember.String.underscore,n=window.DS;n.DebugAdapter=Ember.DataAdapter.extend({getFilters:function(){return[{name:"isNew",desc:"New"},{name:"isModified",desc:"Modified"},{name:"isClean",desc:"Clean"}]},detect:function(e){return e!==n.Model&&n.Model.detect(e)},columnsForType:function(n){var i=[{name:"id",desc:"Id"}],a=0,o=this;return Ember.A(e(n,"attributes")).forEach(function(e){if(a++>o.attributeLimit)return!1;var n=t(r(e).replace("_"," "));i.push({name:e,desc:n})}),i},getRecords:function(e){return this.get("store").all(e)},getRecordColumnValues:function(t){var r=this,n=0,i={id:e(t,"id")};return t.eachAttribute(function(a){if(n++>r.attributeLimit)return!1;var o=e(t,a);i[a]=o}),i},getRecordKeywords:function(t){var r=[],n=Ember.A(["id"]);return t.eachAttribute(function(e){n.push(e)}),n.forEach(function(n){r.push(e(t,n))}),r},getRecordFilterValues:function(e){return{isNew:e.get("isNew"),isModified:e.get("isDirty")&&!e.get("isNew"),isClean:!e.get("isDirty")}},getRecordColor:function(e){var t="black";return e.get("isNew")?t="green":e.get("isDirty")&&(t="blue"),t},observeRecord:function(e,t){var r=Ember.A(),n=this,i=Ember.A(["id","isNew","isDirty"]);e.eachAttribute(function(e){i.push(e)}),i.forEach(function(i){var a=function(){t(n.wrapRecord(e))};Ember.addObserver(e,i,a),r.push(function(){Ember.removeObserver(e,i,a)})});var a=function(){r.forEach(function(e){e()})};return a}})}(),function(){DS.Transform=Ember.Object.extend({serialize:Ember.required(),deserialize:Ember.required()})}(),function(){DS.BooleanTransform=DS.Transform.extend({deserialize:function(e){var t=typeof e;return"boolean"===t?e:"string"===t?null!==e.match(/^true$|^t$|^1$/i):"number"===t?1===e:!1},serialize:function(e){return Boolean(e)}})}(),function(){DS.DateTransform=DS.Transform.extend({deserialize:function(e){var t=typeof e;return"string"===t?new Date(Ember.Date.parse(e)):"number"===t?new Date(e):null===e||void 0===e?e:null},serialize:function(e){if(e instanceof Date){var t=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],r=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],n=function(e){return 10>e?"0"+e:""+e},i=e.getUTCFullYear(),a=e.getUTCMonth(),o=e.getUTCDate(),s=e.getUTCDay(),c=e.getUTCHours(),d=e.getUTCMinutes(),u=e.getUTCSeconds(),l=t[s],h=n(o),f=r[a];return l+", "+h+" "+f+" "+i+" "+n(c)+":"+n(d)+":"+n(u)+" GMT"}return null}})}(),function(){var e=Ember.isEmpty;DS.NumberTransform=DS.Transform.extend({deserialize:function(t){return e(t)?null:Number(t)},serialize:function(t){return e(t)?null:Number(t)}})}(),function(){var e=Ember.isNone;Ember.isEmpty,DS.StringTransform=DS.Transform.extend({deserialize:function(t){return e(t)?null:String(t)},serialize:function(t){return e(t)?null:String(t)}})}(),function(){Ember.set,Ember.onLoad("Ember.Application",function(e){e.initializer({name:"store",initialize:function(e,t){t.register("store:main",t.Store||DS.Store),t.register("serializer:_default",DS.JSONSerializer),t.register("serializer:_rest",DS.RESTSerializer),t.register("adapter:_rest",DS.RESTAdapter),e.lookup("store:main")}}),e.initializer({name:"transforms",initialize:function(e,t){t.register("transform:boolean",DS.BooleanTransform),t.register("transform:date",DS.DateTransform),t.register("transform:number",DS.NumberTransform),t.register("transform:string",DS.StringTransform)}}),e.initializer({name:"dataAdapter",initialize:function(e,t){t.register("dataAdapter:main",DS.DebugAdapter)}}),e.initializer({name:"injectStore",initialize:function(e,t){t.inject("controller","store","store:main"),t.inject("route","store","store:main"),t.inject("serializer","store","store:main"),t.inject("dataAdapter","store","store:main")}})})}(),function(){Ember.Date=Ember.Date||{};var e=Date.parse,t=[1,4,5,6,7,10,11];Ember.Date.parse=function(r){var n,i,a=0;if(i=/^(\d{4}|[+\-]\d{6})(?:-(\d{2})(?:-(\d{2}))?)?(?:T(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{3}))?)?(?:(Z)|([+\-])(\d{2})(?::(\d{2}))?)?)?$/.exec(r)){for(var o,s=0;o=t[s];++s)i[o]=+i[o]||0;i[2]=(+i[2]||1)-1,i[3]=+i[3]||1,"Z"!==i[8]&&void 0!==i[9]&&(a=60*i[10]+i[11],"+"===i[9]&&(a=0-a)),n=Date.UTC(i[1],i[2],i[3],i[4],i[5]+a,i[6],i[7])}else n=e?e(r):0/0;return n},(Ember.EXTEND_PROTOTYPES===!0||Ember.EXTEND_PROTOTYPES.Date)&&(Date.parse=Ember.Date.parse)}(),function(){var e=Ember.get;Ember.set,DS.RecordArray=Ember.ArrayProxy.extend(Ember.Evented,{type:null,content:null,isLoaded:!1,isUpdating:!1,store:null,objectAtContent:function(t){var r=e(this,"content");return r.objectAt(t)},update:function(){if(!e(this,"isUpdating")){var t=e(this,"store"),r=e(this,"type");t.fetchAll(r,this)}},addRecord:function(t){e(this,"content").addObject(t)},removeRecord:function(t){e(this,"content").removeObject(t)}})}(),function(){var e=Ember.get;DS.FilteredRecordArray=DS.RecordArray.extend({filterFunction:null,isLoaded:!0,replace:function(){var t=e(this,"type").toString();throw new Error("The result of a client-side filter (on "+t+") is immutable.")},updateFilter:Ember.observer(function(){var t=e(this,"manager");t.updateFilter(this,e(this,"type"),e(this,"filterFunction"))},"filterFunction")})}(),function(){var e=Ember.get;Ember.set,DS.AdapterPopulatedRecordArray=DS.RecordArray.extend({query:null,replace:function(){var t=e(this,"type").toString();throw new Error("The result of a server query (on "+t+") is immutable.")},load:function(t){var r=e(this,"store"),n=e(this,"type"),i=r.pushMany(n,t);this.setProperties({content:Ember.A(i),isLoaded:!0}),Ember.run.once(this,"trigger","didLoad")}})}(),function(){var e=Ember.get,t=Ember.set,r=Ember.EnumerableUtils.map;DS.ManyArray=DS.RecordArray.extend({init:function(){this._super.apply(this,arguments),this._changesToSync=Ember.OrderedSet.create()},owner:null,isPolymorphic:!1,isLoaded:!1,loadingRecordsCount:function(e){this.loadingRecordsCount=e},loadedRecord:function(){this.loadingRecordsCount--,0===this.loadingRecordsCount&&(t(this,"isLoaded",!0),this.trigger("didLoad"))},fetch:function(){var t=e(this,"content"),r=e(this,"store"),n=e(this,"owner"),i=t.filterProperty("isEmpty",!0);r.fetchMany(i,n)},replaceContent:function(e,t,n){n=r(n,function(e){return e},this),this._super(e,t,n)},arrangedContentDidChange:function(){this.fetch()},arrayContentWillChange:function(t,r){var n=e(this,"owner"),i=e(this,"name");if(!n._suspendedRelationships)for(var a=t;t+r>a;a++){var o=e(this,"content").objectAt(a),s=DS.RelationshipChange.createChange(n,o,e(this,"store"),{parentType:n.constructor,changeType:"remove",kind:"hasMany",key:i});this._changesToSync.add(s)}return this._super.apply(this,arguments)},arrayContentDidChange:function(t,r,n){this._super.apply(this,arguments);var i=e(this,"owner"),a=e(this,"name"),o=e(this,"store");if(!i._suspendedRelationships){for(var s=t;t+n>s;s++){var c=e(this,"content").objectAt(s),d=DS.RelationshipChange.createChange(i,c,o,{parentType:i.constructor,changeType:"add",kind:"hasMany",key:a});d.hasManyName=a,this._changesToSync.add(d)}this._changesToSync.forEach(function(e){e.sync()}),this._changesToSync.clear()}},createRecord:function(t){var r,n=e(this,"owner"),i=e(n,"store"),a=e(this,"type");return r=i.createRecord.call(i,a,t),this.pushObject(r),r}})}(),function(){function e(e){var t=Ember.meta(e,!0),r="DS.Mappable",n=t[r];return n||(t[r]={}),t.hasOwnProperty(r)||(t[r]=Ember.create(t[r])),t[r]}Ember.get;var t=Ember.ArrayPolyfills.forEach,r=function(e){return e},n=function(e){return e},i=function(e,t){return t};DS._Mappable=Ember.Mixin.create({createInstanceMapFor:function(t){var r=e(this);if(r.values=r.values||{},r.values[t])return r.values[t];for(var n=r.values[t]=new Ember.Map,i=this.constructor;i&&i!==DS.Store;)this._copyMap(t,i,n),i=i.superclass;return r.values[t]=n,n},_copyMap:function(a,o,s){function c(e,t){var a=(o.transformMapKey||n)(e,t),c=(o.transformMapValue||i)(e,t),d=s.get(a),u=c;d&&(u=(this.constructor.resolveMapConflict||r)(d,u)),s.set(a,u)}var d=e(o),u=d[a];u&&t.call(u,c,this)}}),DS._Mappable.generateMapFunctionFor=function(t,r){return function(n,i){var a=e(this),o=a[t]||Ember.MapWithDefault.create({defaultValue:function(){return{}}});r.call(this,n,i,o),a[t]=o}}}(),function(){function e(e,r,i){return r.eachRelationship(function(r,a){if(!i.links||!i.links[r]){var o=(a.type,i[r]);null!=o&&("belongsTo"===a.kind?t(e,i,r,a,o):"hasMany"===a.kind&&n(e,i,r,a,o))}}),i}function t(e,t,n,i,a){if(!(g(a)||a instanceof DS.Model)){var o;"number"==typeof a||"string"==typeof a?(o=r(i,n,t),t[n]=e.recordForId(o,a)):"object"==typeof a&&(t[n]=e.recordForId(a.type,a.id))}}function r(e,t,r){return e.options.polymorphic?r[t+"_type"]:e.type}function n(e,r,n,i,a){for(var o=0,s=a.length;s>o;o++)t(e,a,o,i,a[o])}function i(e){return DS.PromiseObject.create({promise:e})}function a(e){return DS.PromiseArray.create({promise:e})}function o(e,t,r){return e.lookup("serializer:"+t)||e.lookup("serializer:application")||e.lookup("serializer:"+r)||e.lookup("serializer:_default")}function s(e,t){var r=e.serializer,n=e.defaultSerializer,i=e.container;return i&&void 0===r&&(r=o(i,t.typeKey,n)),(null===r||void 0===r)&&(r={extract:function(e,t,r){return r}}),r}function c(e,t,r,n,i){var a=e.find(t,r,n),o=s(e,r);return E(a).then(function(e){return e=o.extract(t,r,e,n,"find"),t.push(r,e)}).then(i.resolve,i.reject)}function d(e,t,r,n,i,a){var o=e.findMany(t,r,n,i),c=s(e,r);return E(o).then(function(e){e=c.extract(t,r,e,null,"findMany"),t.pushMany(r,e)}).then(a.resolve,a.reject)}function u(e,t,r,n,i,a){var o=e.findHasMany(t,r,n,i),c=s(e,i.type);return E(o).then(function(e){e=c.extract(t,i.type,e,null,"findHasMany");var n=t.pushMany(i.type,e);r.updateHasMany(i.key,n)}).then(a.resolve,a.reject)}function l(e,t,r,n,i){var a=e.findAll(t,r,n),o=s(e,r);return E(a).then(function(e){return e=o.extract(t,r,e,null,"findAll"),t.pushMany(r,e),t.didUpdateAll(r),t.all(r)}).then(i.resolve,i.reject)}function h(e,t,r,n,i,a){var o=e.findQuery(t,r,n,i),c=s(e,r);return E(o).then(function(e){return e=c.extract(t,r,e,null,"findAll"),i.load(e),i}).then(a.resolve,a.reject)}function f(e,t,r,n,i){var a=n.constructor,o=e[r](t,a,n),c=s(e,a);return o.then(function(e){return e=c.extract(t,a,e,p(n,"id"),r),t.didSaveRecord(n,e),n},function(e){throw e instanceof DS.InvalidError?t.recordWasInvalid(n,e.errors):t.recordWasError(n,e),e}).then(i.resolve,i.reject)}var p=Ember.get,m=Ember.set,y=Ember.run.once,g=Ember.isNone,b=Ember.EnumerableUtils.forEach,v=Ember.EnumerableUtils.indexOf,R=Ember.EnumerableUtils.map;Ember.OrderedSet;var E=Ember.RSVP.resolve,S=function(e){return null==e?null:e+""};DS.Store=Ember.Object.extend(DS._Mappable,{init:function(){this.typeMaps={},this.recordArrayManager=DS.RecordArrayManager.create({store:this}),this._relationshipChanges={},this._pendingSave=[]},adapter:"_rest",serialize:function(e,t){return this.serializerFor(e.constructor.typeKey).serialize(e,t)},defaultAdapter:Ember.computed(function(){var e=p(this,"adapter");return"string"==typeof e&&(e=this.container.lookup("adapter:"+e)||this.container.lookup("adapter:application")||this.container.lookup("adapter:_rest")),DS.Adapter.detect(e)&&(e=e.create({container:this.container})),e}).property("adapter"),createRecord:function(e,t){e=this.modelFor(e),t=t||{},g(t.id)&&(t.id=this._generateId(e)),t.id=S(t.id);var r=this.buildRecord(e,t.id);return r.loadedData(),r.setProperties(t),r},_generateId:function(e){var t=this.adapterForType(e);return t&&t.generateIdForRecord?t.generateIdForRecord(this):null},deleteRecord:function(e){e.deleteRecord()},unloadRecord:function(e){e.unloadRecord()},find:function(e,t){return void 0===t?this.findAll(e):"object"===Ember.typeOf(t)?this.findQuery(e,t):this.findById(e,S(t))},findById:function(e,t){e=this.modelFor(e);var r=this.getById(e,t);return p(r,"isEmpty")?i(this.fetchRecord(r)):i(E(r))},findByIds:function(e,t){var r=this;return a(Ember.RSVP.all(R(t,function(t){return r.findById(e,t)})).then(function(e){return Ember.A(e)}))},fetchRecord:function(e){var t=e.constructor,r=p(e,"id"),n=Ember.RSVP.defer();e.loadingData();var i=this.adapterForType(t);return c(i,this,t,r,n),n.promise},getById:function(e,t){return e=this.modelFor(e),this.hasRecordForId(e,t)?this.recordForId(e,t):this.buildRecord(e,t)},reloadRecord:function(e,t){var r=e.constructor,n=this.adapterForType(r),i=p(e,"id");return c(n,this,r,i,t)},fetchMany:function(e,t,r){if(e.length){var n=Ember.MapWithDefault.create({defaultValue:function(){return Ember.A()}});b(e,function(e){n.get(e.constructor).push(e)}),b(n,function(e,n){var i=n.mapProperty("id"),a=this.adapterForType(e);d(a,this,e,i,t,r)},this)}},hasRecordForId:function(e,t){return t=S(t),!!this.typeMapFor(e).idToRecord[t]},recordForId:function(e,t){e=this.modelFor(e),t=S(t);var r=this.typeMapFor(e).idToRecord[t];return r||(r=this.buildRecord(e,t)),r},findMany:function(e,t,r,n){r=this.modelFor(r),t=Ember.A(t);var i=t.filterProperty("isEmpty",!0),a=this.recordArrayManager.createManyArray(r,t);return b(i,function(e){e.loadingData()}),a.loadingRecordsCount=i.length,i.length?(b(i,function(e){this.recordArrayManager.registerWaitingRecordArray(e,a)},this),this.fetchMany(i,e,n)):(n&&n.resolve(),a.set("isLoaded",!0),Ember.run.once(a,"trigger","didLoad")),a},findHasMany:function(e,t,r,n){var i=this.adapterForType(e.constructor),a=this.recordArrayManager.createManyArray(r.type,Ember.A([]));return u(i,this,e,t,r,n),a},findQuery:function(e,t){e=this.modelFor(e);var r=DS.AdapterPopulatedRecordArray.create({type:e,query:t,content:Ember.A(),store:this}),n=this.adapterForType(e),i=Ember.RSVP.defer();return h(n,this,e,t,r,i),a(i.promise)},findAll:function(e){return e=this.modelFor(e),this.fetchAll(e,this.all(e))},fetchAll:function(e,t){var r=this.adapterForType(e),n=this.typeMapFor(e).metadata.since,i=Ember.RSVP.defer();return m(t,"isUpdating",!0),l(r,this,e,n,i),a(i.promise)},didUpdateAll:function(e){var t=this.typeMapFor(e).findAllCache;m(t,"isUpdating",!1)},all:function(e){e=this.modelFor(e);var t=this.typeMapFor(e),r=t.findAllCache;if(r)return r;var n=DS.RecordArray.create({type:e,content:Ember.A(),store:this,isLoaded:!0});return this.recordArrayManager.registerFilteredRecordArray(n,e),t.findAllCache=n,n},filter:function(e,t,r){var n;3===arguments.length?n=this.findQuery(e,t):2===arguments.length&&(r=t),e=this.modelFor(e);var i=DS.FilteredRecordArray.create({type:e,content:Ember.A(),store:this,manager:this.recordArrayManager,filterFunction:r});return this.recordArrayManager.registerFilteredRecordArray(i,e,r),n?n.then(function(){return i}):i},recordIsLoaded:function(e,t){return this.hasRecordForId(e,t)?!p(this.recordForId(e,t),"isEmpty"):!1},dataWasUpdated:function(e,t){p(t,"isDeleted")||p(t,"isLoaded")&&this.recordArrayManager.recordDidChange(t)},scheduleSave:function(e,t){e.adapterWillCommit(),this._pendingSave.push([e,t]),y(this,"flushPendingSave")},flushPendingSave:function(){var e=this._pendingSave.slice();this._pendingSave=[],b(e,function(e){var t,r=e[0],n=e[1],i=this.adapterForType(r.constructor);t=p(r,"isNew")?"createRecord":p(r,"isDeleted")?"deleteRecord":"updateRecord",f(i,this,t,r,n)},this)},didSaveRecord:function(e,t){t&&this.updateId(e,t),e.adapterDidCommit(t)},recordWasInvalid:function(e,t){e.adapterDidInvalidate(t)},recordWasError:function(e){e.adapterDidError()},updateId:function(e,t){var r=(p(e,"id"),S(t.id));this.typeMapFor(e.constructor).idToRecord[r]=e,m(e,"id",r)},typeMapFor:function(e){var t,r=p(this,"typeMaps"),n=Ember.guidFor(e);return(t=r[n])?t:(t={idToRecord:{},records:[],metadata:{}},r[n]=t,t)},_load:function(e,t,r){var n=S(t.id),i=this.recordForId(e,n);return i.setupData(t,r),this.recordArrayManager.recordDidChange(i),i},modelFor:function(e){if("string"!=typeof e)return e;var t=this.container.lookupFactory("model:"+e);return t.store=this,t.typeKey=e,t},push:function(t,r,n){return this.serializerFor(t),t=this.modelFor(t),r=e(this,t,r),this._load(t,r,n),this.recordForId(t,r.id)},update:function(e,t){return this.push(e,t,!0)},pushMany:function(e,t){return R(t,function(t){return this.push(e,t)},this)},metaForType:function(e,t){e=this.modelFor(e),Ember.merge(this.typeMapFor(e).metadata,t)},buildRecord:function(e,t,r){var n=this.typeMapFor(e),i=n.idToRecord,a=e._create({id:t,store:this});return r&&a.setupData(r),t&&(i[t]=a),n.records.push(a),a},dematerializeRecord:function(e){var t=e.constructor,r=this.typeMapFor(t),n=p(e,"id");e.updateRecordArrays(),n&&delete r.idToRecord[n];var i=v(r.records,e);r.records.splice(i,1)},addRelationshipChangeFor:function(e,t,r,n,i){var a=e.clientId,o=r?r:r,s=t+n,c=this._relationshipChanges;a in c||(c[a]={}),o in c[a]||(c[a][o]={}),s in c[a][o]||(c[a][o][s]={}),c[a][o][s][i.changeType]=i},removeRelationshipChangeFor:function(e,t,r,n,i){var a=e.clientId,o=r?r.clientId:r,s=this._relationshipChanges,c=t+n;a in s&&o in s[a]&&c in s[a][o]&&delete s[a][o][c][i]},relationshipChangePairsFor:function(e){var t=[];if(!e)return t;var r=this._relationshipChanges[e.clientId];for(var n in r)if(r.hasOwnProperty(n))for(var i in r[n])r[n].hasOwnProperty(i)&&t.push(r[n][i]);return t},adapterForType:function(e){var t,r=this.container;return r&&(t=r.lookup("adapter:"+e.typeKey)||r.lookup("adapter:application")),t||p(this,"defaultAdapter")},serializerFor:function(e){e=this.modelFor(e);var t=this.adapterForType(e);return o(this.container,e.typeKey,t&&t.defaultSerializer)}}),DS.PromiseArray=Ember.ArrayProxy.extend(Ember.PromiseProxyMixin),DS.PromiseObject=Ember.ObjectProxy.extend(Ember.PromiseProxyMixin)}(),function(){function e(t){var r,n={};for(var i in t)r=t[i],n[i]=r&&"object"==typeof r?e(r):r;return n}function t(e,t){for(var r in t)e[r]=t[r];return e}function r(r){var n=e(c);return t(n,r)}function n(e,r,i){e=t(r?Ember.create(r):{},e),e.parentState=r,e.stateName=i;for(var a in e)e.hasOwnProperty(a)&&"parentState"!==a&&"stateName"!==a&&"object"==typeof e[a]&&(e[a]=n(e[a],e,i+"."+a));return e}var i=Ember.get,a=Ember.set;Ember.run.once,Ember.ArrayPolyfills.map;var o=function(e){var t,r,n,i=Ember.keys(e);for(t=0,r=i.length;r>t;t++)if(n=i[t],e.hasOwnProperty(n)&&e[n])return!0;return!1},s=function(e,t){t.value!==t.oldValue&&(e.send("becomeDirty"),e.updateRecordArraysLater())},c={initialState:"uncommitted",isDirty:!0,uncommitted:{didSetProperty:s,pushedData:Ember.K,becomeDirty:Ember.K,willCommit:function(e){e.transitionTo("inFlight")},reloadRecord:function(e,t){i(e,"store").reloadRecord(e,t)},rolledBack:function(e){e.transitionTo("loaded.saved")},becameInvalid:function(e){e.transitionTo("invalid")},rollback:function(e){e.rollback()}},inFlight:{isSaving:!0,didSetProperty:s,becomeDirty:Ember.K,pushedData:Ember.K,willCommit:Ember.K,didCommit:function(e){var t=i(this,"dirtyType");e.transitionTo("saved"),e.send("invokeLifecycleCallbacks",t)},becameInvalid:function(e,t){a(e,"errors",t),e.transitionTo("invalid"),e.send("invokeLifecycleCallbacks")},becameError:function(e){e.transitionTo("uncommitted"),e.triggerLater("becameError",e)}},invalid:{isValid:!1,deleteRecord:function(e){e.transitionTo("deleted.uncommitted"),e.clearRelationships()},didSetProperty:function(e,t){var r=i(e,"errors"),n=t.name;a(r,n,null),o(r)||e.send("becameValid"),s(e,t)},becomeDirty:Ember.K,rollback:function(e){e.send("becameValid"),e.send("rollback")},becameValid:function(e){e.transitionTo("uncommitted")},invokeLifecycleCallbacks:function(e){e.triggerLater("becameInvalid",e)}}},d=r({dirtyType:"created",isNew:!0});d.uncommitted.rolledBack=function(e){e.transitionTo("deleted.saved")};var u=r({dirtyType:"updated"});d.uncommitted.deleteRecord=function(e){e.clearRelationships(),e.transitionTo("deleted.saved")},d.uncommitted.rollback=function(e){c.uncommitted.rollback.apply(this,arguments),e.transitionTo("deleted.saved")},u.uncommitted.deleteRecord=function(e){e.transitionTo("deleted.uncommitted"),e.clearRelationships()};var l={isEmpty:!1,isLoading:!1,isLoaded:!1,isDirty:!1,isSaving:!1,isDeleted:!1,isNew:!1,isValid:!0,rolledBack:Ember.K,empty:{isEmpty:!0,loadingData:function(e){e.transitionTo("loading")},loadedData:function(e){e.transitionTo("loaded.created.uncommitted"),e.suspendRelationshipObservers(function(){e.notifyPropertyChange("data")})},pushedData:function(e){e.transitionTo("loaded.saved")}},loading:{isLoading:!0,pushedData:function(e){e.transitionTo("loaded.saved"),e.triggerLater("didLoad"),a(e,"isError",!1)},becameError:function(e){e.triggerLater("becameError",e)}},loaded:{initialState:"saved",isLoaded:!0,saved:{setup:function(e){var t=e._attributes,r=!1;for(var n in t)if(t.hasOwnProperty(n)){r=!0;break}r&&e.adapterDidDirty()},didSetProperty:s,pushedData:Ember.K,becomeDirty:function(e){e.transitionTo("updated.uncommitted")},willCommit:function(e){e.transitionTo("updated.inFlight")},reloadRecord:function(e,t){i(e,"store").reloadRecord(e,t)},deleteRecord:function(e){e.transitionTo("deleted.uncommitted"),e.clearRelationships()},unloadRecord:function(e){e.clearRelationships(),e.transitionTo("deleted.saved")},didCommit:function(e){e.send("invokeLifecycleCallbacks",i(e,"lastDirtyType"))}},created:d,updated:u},deleted:{initialState:"uncommitted",dirtyType:"deleted",isDeleted:!0,isLoaded:!0,isDirty:!0,setup:function(e){var t=i(e,"store");t.recordArrayManager.remove(e)},uncommitted:{willCommit:function(e){e.transitionTo("inFlight")},rollback:function(e){e.rollback()},becomeDirty:Ember.K,deleteRecord:Ember.K,rolledBack:function(e){e.transitionTo("loaded.saved")}},inFlight:{isSaving:!0,willCommit:Ember.K,didCommit:function(e){e.transitionTo("saved"),e.send("invokeLifecycleCallbacks")},becameError:function(e){e.transitionTo("uncommitted"),e.triggerLater("becameError",e)}},saved:{isDirty:!1,setup:function(e){var t=i(e,"store");t.dematerializeRecord(e)},invokeLifecycleCallbacks:function(e){e.triggerLater("didDelete",e),e.triggerLater("didCommit",e)}}},invokeLifecycleCallbacks:function(e,t){"created"===t?e.triggerLater("didCreate",e):e.triggerLater("didUpdate",e),e.triggerLater("didCommit",e)}};({}).hasOwnProperty,l=n(l,null,"root"),DS.RootState=l}(),function(){var e=Ember.get,t=Ember.set,r=(Ember.EnumerableUtils.map,Ember.merge),n=Ember.run.once;Ember.ArrayPolyfills.map;var i=Ember.computed(function(t){return e(e(this,"currentState"),t)}).property("currentState").readOnly();DS.Model=Ember.Object.extend(Ember.Evented,{isEmpty:i,isLoading:i,isLoaded:i,isDirty:i,isSaving:i,isDeleted:i,isNew:i,isValid:i,dirtyType:i,isError:!1,isReloading:!1,clientId:null,id:null,transaction:null,currentState:null,errors:null,serialize:function(t){var r=e(this,"store");return r.serialize(this,t)},toJSON:function(e){var t=DS.JSONSerializer.create();return t.serialize(this,e)},didLoad:Ember.K,didReload:Ember.K,didUpdate:Ember.K,didCreate:Ember.K,didDelete:Ember.K,becameInvalid:Ember.K,becameError:Ember.K,data:Ember.computed(function(){return this._data=this._data||{},this._data}).property(),_data:null,init:function(){t(this,"currentState",DS.RootState.empty),this._super(),this._setup()},_setup:function(){this._changesToSync={},this._deferredTriggers=[],this._data={},this._attributes={},this._inFlightAttributes={},this._relationships={}},send:function(t,r){var n=e(this,"currentState");return n[t]||this._unhandledEvent(n,t,r),n[t](this,r)},transitionTo:function(r){var n=r.split(".",1),i=e(this,"currentState"),a=i;do a.exit&&a.exit(this),a=a.parentState;while(!a.hasOwnProperty(n));var o,s,c=r.split("."),d=[],u=[];for(o=0,s=c.length;s>o;o++)a=a[c[o]],a.enter&&u.push(a),a.setup&&d.push(a);for(o=0,s=u.length;s>o;o++)u[o].enter(this);for(t(this,"currentState",a),o=0,s=d.length;s>o;o++)d[o].setup(this)},_unhandledEvent:function(e,t,r){var n="Attempted to handle event `"+t+"` ";throw n+="on "+String(this)+" while in state ",n+=e.stateName+". ",void 0!==r&&(n+="Called with "+Ember.inspect(r)+"."),new Ember.Error(n)},withTransaction:function(t){var r=e(this,"transaction");r&&t(r)},loadingData:function(){this.send("loadingData")},loadedData:function(){this.send("loadedData")},pushedData:function(){this.send("pushedData")},deleteRecord:function(){this.send("deleteRecord")},unloadRecord:function(){this.send("unloadRecord")},clearRelationships:function(){this.eachRelationship(function(e,r){if("belongsTo"===r.kind)t(this,e,null);else if("hasMany"===r.kind){var n=this._relationships[r.name];n&&n.clear()}},this)},updateRecordArrays:function(){var t=e(this,"store");t&&t.dataWasUpdated(this.constructor,this)},adapterWillCommit:function(){this.send("willCommit")},adapterDidCommit:function(e){t(this,"isError",!1),e?this._data=e:Ember.mixin(this._data,this._inFlightAttributes),this._inFlightAttributes={},this.send("didCommit"),this.updateRecordArraysLater(),e&&this.suspendRelationshipObservers(function(){this.notifyPropertyChange("data")})},adapterDidDirty:function(){this.send("becomeDirty"),this.updateRecordArraysLater()},dataDidChange:Ember.observer(function(){this.reloadHasManys()},"data"),reloadHasManys:function(){var t=e(this.constructor,"relationshipsByName");this.updateRecordArraysLater(),t.forEach(function(e,t){"hasMany"===t.kind&&this.hasManyDidChange(t.key)},this)},hasManyDidChange:function(r){var n=this._relationships[r];if(n){e(this.constructor,"relationshipsByName").get(r).type,e(this,"store");var i=this._data[r]||[];t(n,"content",Ember.A(i)),t(n,"isLoaded",!0),n.trigger("didLoad")}},updateRecordArraysLater:function(){Ember.run.once(this,this.updateRecordArrays)},setupData:function(e,t){t?Ember.merge(this._data,e):this._data=e;var r=this._relationships;this.eachRelationship(function(e,t){t.options.async&&(r[e]=null)}),e&&this.pushedData(),this.suspendRelationshipObservers(function(){this.notifyPropertyChange("data")})},materializeId:function(e){t(this,"id",e)},materializeAttributes:function(e){r(this._data,e)},materializeAttribute:function(e,t){this._data[e]=t},updateHasMany:function(e,t){this._data[e]=t,this.hasManyDidChange(e)},rollback:function(){this._attributes={},this.send("rolledBack"),this.suspendRelationshipObservers(function(){this.notifyPropertyChange("data")})},toStringExtension:function(){return e(this,"id")},suspendRelationshipObservers:function(t,r){var n=e(this.constructor,"relationshipNames").belongsTo,i=this;try{this._suspendedRelationships=!0,Ember._suspendObservers(i,n,null,"belongsToDidChange",function(){Ember._suspendBeforeObservers(i,n,null,"belongsToWillChange",function(){t.call(r||i)})})}finally{this._suspendedRelationships=!1}},save:function(){var e=Ember.RSVP.defer();return this.get("store").scheduleSave(this,e),this._inFlightAttributes=this._attributes,this._attributes={},DS.PromiseObject.create({promise:e.promise})},reload:function(){t(this,"isReloading",!0);var e=Ember.RSVP.defer(),r=this;return e.promise=e.promise.then(function(){return r.set("isReloading",!1),r.set("isError",!1),r},function(e){throw r.set("isError",!0),e}),this.send("reloadRecord",e),DS.PromiseObject.create({promise:e.promise})},adapterDidUpdateAttribute:function(e,t){void 0!==t?(this._data[e]=t,this.notifyPropertyChange(e)):this._data[e]=this._inFlightAttributes[e],this.updateRecordArraysLater()},adapterDidInvalidate:function(e){this.send("becameInvalid",e)},adapterDidError:function(){this.send("becameError"),t(this,"isError",!0)},trigger:function(e){Ember.tryInvoke(this,e,[].slice.call(arguments,1)),this._super.apply(this,arguments)},triggerLater:function(){this._deferredTriggers.push(arguments),n(this,"_triggerDeferredTriggers")},_triggerDeferredTriggers:function(){for(var e=0,t=this._deferredTriggers.length;t>e;e++)this.trigger.apply(this,this._deferredTriggers[e]);this._deferredTriggers=[]}}),DS.Model.reopenClass({_create:DS.Model.create,create:function(){throw new Ember.Error("You should not call `create` on a model. Instead, call `store.createRecord` with the attributes you would like to set.")}})}(),function(){function e(e,t){return"function"==typeof t.defaultValue?t.defaultValue():t.defaultValue}function t(e,t){return e._attributes.hasOwnProperty(t)||e._inFlightAttributes.hasOwnProperty(t)||e._data.hasOwnProperty(t)}function r(e,t){return e._attributes.hasOwnProperty(t)?e._attributes[t]:e._inFlightAttributes.hasOwnProperty(t)?e._inFlightAttributes[t]:e._data[t]}var n=Ember.get;DS.Model.reopenClass({attributes:Ember.computed(function(){var e=Ember.Map.create();return this.eachComputedProperty(function(t,r){r.isAttribute&&(r.name=t,e.set(t,r))}),e}),transformedAttributes:Ember.computed(function(){var e=Ember.Map.create();return this.eachAttribute(function(t,r){r.type&&e.set(t,r.type)}),e}),eachAttribute:function(e,t){n(this,"attributes").forEach(function(r,n){e.call(t,r,n)},t)},eachTransformedAttribute:function(e,t){n(this,"transformedAttributes").forEach(function(r,n){e.call(t,r,n)})}}),DS.Model.reopen({eachAttribute:function(e,t){this.constructor.eachAttribute(e,t)}}),DS.attr=function(n,i){i=i||{};var a={type:n,isAttribute:!0,options:i};return Ember.computed(function(n,a){return arguments.length>1?(this.send("didSetProperty",{name:n,oldValue:this._attributes[n]||this._inFlightAttributes[n]||this._data[n],value:a}),this._attributes[n]=a,a):t(this,n)?r(this,n):e(this,i,n)}).property("data").meta(a)}}(),function(){var e=DS.AttributeChange=function(e){this.record=e.record,this.store=e.store,this.name=e.name,this.value=e.value,this.oldValue=e.oldValue};e.createChange=function(t){return new e(t)},e.prototype={sync:function(){this.value!==this.oldValue&&(this.record.send("becomeDirty"),this.record.updateRecordArraysLater()),this.destroy()},destroy:function(){delete this.record._changesToSync[this.name]}}}(),function(){function e(e){return"object"==typeof e&&(!e.then||"function"!=typeof e.then)}var t=Ember.get,r=Ember.set,n=Ember.EnumerableUtils.forEach;DS.RelationshipChange=function(e){this.parentRecord=e.parentRecord,this.childRecord=e.childRecord,this.firstRecord=e.firstRecord,this.firstRecordKind=e.firstRecordKind,this.firstRecordName=e.firstRecordName,this.secondRecord=e.secondRecord,this.secondRecordKind=e.secondRecordKind,this.secondRecordName=e.secondRecordName,this.changeType=e.changeType,this.store=e.store,this.committed={}},DS.RelationshipChangeAdd=function(e){DS.RelationshipChange.call(this,e)},DS.RelationshipChangeRemove=function(e){DS.RelationshipChange.call(this,e)},DS.RelationshipChange.create=function(e){return new DS.RelationshipChange(e)},DS.RelationshipChangeAdd.create=function(e){return new DS.RelationshipChangeAdd(e)},DS.RelationshipChangeRemove.create=function(e){return new DS.RelationshipChangeRemove(e)},DS.OneToManyChange={},DS.OneToNoneChange={},DS.ManyToNoneChange={},DS.OneToOneChange={},DS.ManyToManyChange={},DS.RelationshipChange._createChange=function(e){return"add"===e.changeType?DS.RelationshipChangeAdd.create(e):"remove"===e.changeType?DS.RelationshipChangeRemove.create(e):void 0
15
- },DS.RelationshipChange.determineRelationshipType=function(e,t){var r,n,i=t.key,a=t.kind,o=e.inverseFor(i);return o&&(r=o.name,n=o.kind),o?"belongsTo"===n?"belongsTo"===a?"oneToOne":"manyToOne":"belongsTo"===a?"oneToMany":"manyToMany":"belongsTo"===a?"oneToNone":"manyToNone"},DS.RelationshipChange.createChange=function(e,t,r,n){var i,a=e.constructor;return i=DS.RelationshipChange.determineRelationshipType(a,n),"oneToMany"===i?DS.OneToManyChange.createChange(e,t,r,n):"manyToOne"===i?DS.OneToManyChange.createChange(t,e,r,n):"oneToNone"===i?DS.OneToNoneChange.createChange(e,t,r,n):"manyToNone"===i?DS.ManyToNoneChange.createChange(e,t,r,n):"oneToOne"===i?DS.OneToOneChange.createChange(e,t,r,n):"manyToMany"===i?DS.ManyToManyChange.createChange(e,t,r,n):void 0},DS.OneToNoneChange.createChange=function(e,t,r,n){var i=n.key,a=DS.RelationshipChange._createChange({parentRecord:t,childRecord:e,firstRecord:e,store:r,changeType:n.changeType,firstRecordName:i,firstRecordKind:"belongsTo"});return r.addRelationshipChangeFor(e,i,t,null,a),a},DS.ManyToNoneChange.createChange=function(e,t,r,n){var i=n.key,a=DS.RelationshipChange._createChange({parentRecord:e,childRecord:t,secondRecord:e,store:r,changeType:n.changeType,secondRecordName:n.key,secondRecordKind:"hasMany"});return r.addRelationshipChangeFor(e,i,t,null,a),a},DS.ManyToManyChange.createChange=function(e,t,r,n){var i=n.key,a=DS.RelationshipChange._createChange({parentRecord:t,childRecord:e,firstRecord:e,secondRecord:t,firstRecordKind:"hasMany",secondRecordKind:"hasMany",store:r,changeType:n.changeType,firstRecordName:i});return r.addRelationshipChangeFor(e,i,t,null,a),a},DS.OneToOneChange.createChange=function(e,t,r,n){var i;n.parentType?i=n.parentType.inverseFor(n.key).name:n.key&&(i=n.key);var a=DS.RelationshipChange._createChange({parentRecord:t,childRecord:e,firstRecord:e,secondRecord:t,firstRecordKind:"belongsTo",secondRecordKind:"belongsTo",store:r,changeType:n.changeType,firstRecordName:i});return r.addRelationshipChangeFor(e,i,t,null,a),a},DS.OneToOneChange.maintainInvariant=function(e,r,n,i){if("add"===e.changeType&&r.recordIsMaterialized(n)){var a=t(n,i);if(a){var o=DS.OneToOneChange.createChange(n,a,r,{parentType:e.parentType,hasManyName:e.hasManyName,changeType:"remove",key:e.key});r.addRelationshipChangeFor(n,i,e.parentRecord,null,o),o.sync()}}},DS.OneToManyChange.createChange=function(e,t,r,n){var i;n.parentType?(i=n.parentType.inverseFor(n.key).name,DS.OneToManyChange.maintainInvariant(n,r,e,i)):n.key&&(i=n.key);var a=DS.RelationshipChange._createChange({parentRecord:t,childRecord:e,firstRecord:e,secondRecord:t,firstRecordKind:"belongsTo",secondRecordKind:"hasMany",store:r,changeType:n.changeType,firstRecordName:i});return r.addRelationshipChangeFor(e,i,t,a.getSecondRecordName(),a),a},DS.OneToManyChange.maintainInvariant=function(e,r,n,i){if("add"===e.changeType&&n){var a=t(n,i);if(a){var o=DS.OneToManyChange.createChange(n,a,r,{parentType:e.parentType,hasManyName:e.hasManyName,changeType:"remove",key:e.key});r.addRelationshipChangeFor(n,i,e.parentRecord,o.getSecondRecordName(),o),o.sync()}}},DS.RelationshipChange.prototype={getSecondRecordName:function(){var e,t=this.secondRecordName;if(!t){if(e=this.secondRecord,!e)return;var r=this.firstRecord.constructor,n=r.inverseFor(this.firstRecordName);this.secondRecordName=n.name}return this.secondRecordName},getFirstRecordName:function(){var e=this.firstRecordName;return e},destroy:function(){var e=this.childRecord,t=this.getFirstRecordName(),r=this.getSecondRecordName(),n=this.store;n.removeRelationshipChangeFor(e,t,this.parentRecord,r,this.changeType)},getSecondRecord:function(){return this.secondRecord},getFirstRecord:function(){return this.firstRecord},coalesce:function(){var e=this.store.relationshipChangePairsFor(this.firstRecord);n(e,function(e){var t=e.add,r=e.remove;t&&r&&(t.destroy(),r.destroy())})}},DS.RelationshipChangeAdd.prototype=Ember.create(DS.RelationshipChange.create({})),DS.RelationshipChangeRemove.prototype=Ember.create(DS.RelationshipChange.create({})),DS.RelationshipChangeAdd.prototype.changeType="add",DS.RelationshipChangeAdd.prototype.sync=function(){var n=this.getSecondRecordName(),i=this.getFirstRecordName(),a=this.getFirstRecord(),o=this.getSecondRecord();o instanceof DS.Model&&a instanceof DS.Model&&("belongsTo"===this.secondRecordKind?o.suspendRelationshipObservers(function(){r(o,n,a)}):"hasMany"===this.secondRecordKind&&o.suspendRelationshipObservers(function(){var r=t(o,n);e(r)&&r.addObject(a)})),a instanceof DS.Model&&o instanceof DS.Model&&t(a,i)!==o&&("belongsTo"===this.firstRecordKind?a.suspendRelationshipObservers(function(){r(a,i,o)}):"hasMany"===this.firstRecordKind&&a.suspendRelationshipObservers(function(){var r=t(a,i);e(r)&&r.addObject(o)})),this.coalesce()},DS.RelationshipChangeRemove.prototype.changeType="remove",DS.RelationshipChangeRemove.prototype.sync=function(){var n=this.getSecondRecordName(),i=this.getFirstRecordName(),a=this.getFirstRecord(),o=this.getSecondRecord();o instanceof DS.Model&&a instanceof DS.Model&&("belongsTo"===this.secondRecordKind?o.suspendRelationshipObservers(function(){r(o,n,null)}):"hasMany"===this.secondRecordKind&&o.suspendRelationshipObservers(function(){var r=t(o,n);e(r)&&r.removeObject(a)})),a instanceof DS.Model&&t(a,i)&&("belongsTo"===this.firstRecordKind?a.suspendRelationshipObservers(function(){r(a,i,null)}):"hasMany"===this.firstRecordKind&&a.suspendRelationshipObservers(function(){var r=t(a,i);e(r)&&r.removeObject(o)})),this.coalesce()}}(),function(){function e(e,n,i){return Ember.computed(function(e,n){var i,a=t(this,"data"),o=t(this,"store");return 2===arguments.length?void 0===n?null:n:(i=a[e],!r(i)&&t(i,"isEmpty")?o.fetchRecord(i):null)}).property("data").meta(i)}var t=Ember.get,r=(Ember.set,Ember.isNone);DS.belongsTo=function(n,i){i=i||{};var a={type:n,isRelationship:!0,options:i,kind:"belongsTo"};return i.async?e(n,i,a):Ember.computed(function(e,i){var a,o,s=t(this,"data"),c=t(this,"store");return o="string"==typeof n?-1===n.indexOf(".")?c.modelFor(n):t(Ember.lookup,n):n,2===arguments.length?void 0===i?null:i:(a=s[e],r(a)?null:(t(a,"isEmpty")&&c.fetchRecord(a),a))}).property("data").meta(a)},DS.Model.reopen({belongsToWillChange:Ember.beforeObserver(function(e,r){if(t(e,"isLoaded")){var n=t(e,r),i=t(e,"store");if(n){var a=DS.RelationshipChange.createChange(e,n,i,{key:r,kind:"belongsTo",changeType:"remove"});a.sync(),this._changesToSync[r]=a}}}),belongsToDidChange:Ember.immediateObserver(function(e,r){if(t(e,"isLoaded")){var n=t(e,r);if(n){var i=t(e,"store"),a=DS.RelationshipChange.createChange(e,n,i,{key:r,kind:"belongsTo",changeType:"add"});a.sync()}}delete this._changesToSync[r]})})}(),function(){function e(e,r,n){return Ember.computed(function(e){var i=Ember.RSVP.defer(),a=t(this,e,r,function(t,r){var a=r.links&&r.links[e];return a?t.findHasMany(this,a,n,i):t.findMany(this,r[e],n.type,i)}),o=i.promise.then(function(){return a});return DS.PromiseArray.create({promise:o})}).property("data").meta(n)}function t(e,t,r,a){var o=e._relationships;if(o[t])return o[t];var s=n(e,"data"),c=n(e,"store"),d=o[t]=a.call(e,c,s);return i(d,{owner:e,name:t,isPolymorphic:r.polymorphic})}function r(r,n){n=n||{};var i={type:r,isRelationship:!0,options:n,kind:"hasMany"};return n.async?e(r,n,i):Ember.computed(function(e){return t(this,e,n,function(t,r){return r[e],t.findMany(this,r[e],i.type)})}).property("data").meta(i)}var n=Ember.get,i=(Ember.set,Ember.setProperties);Ember.EnumerableUtils.forEach,DS.hasMany=function(e,t){return r(e,t)}}(),function(){var e=Ember.get;Ember.set,DS.Model.reopen({didDefineProperty:function(e,t,r){if(r instanceof Ember.Descriptor){var n=r.meta();n.isRelationship&&"belongsTo"===n.kind&&(Ember.addObserver(e,t,null,"belongsToDidChange"),Ember.addBeforeObserver(e,t,null,"belongsToWillChange")),n.parentType=e.constructor}}}),DS.Model.reopenClass({typeForRelationship:function(t){var r=e(this,"relationshipsByName").get(t);return r&&r.type},inverseFor:function(t){function r(t,n,i){i=i||[];var a=e(n,"relationships");if(a){var o=a.get(t);return o&&i.push.apply(i,a.get(t)),t.superclass&&r(t.superclass,n,i),i}}var n=this.typeForRelationship(t);if(!n)return null;var i=this.metaForProperty(t).options;if(null===i.inverse)return null;var a,o;if(i.inverse)a=i.inverse,o=Ember.get(n,"relationshipsByName").get(a).kind;else{var s=r(this,n);if(0===s.length)return null;a=s[0].name,o=s[0].kind}return{type:n,name:a,kind:o}},relationships:Ember.computed(function(){var e=new Ember.MapWithDefault({defaultValue:function(){return[]}});return this.eachComputedProperty(function(t,r){if(r.isRelationship){"string"==typeof r.type&&(r.type=Ember.get(Ember.lookup,r.type));var n=e.get(r.type);n.push({name:t,kind:r.kind})}}),e}),relationshipNames:Ember.computed(function(){var e={hasMany:[],belongsTo:[]};return this.eachComputedProperty(function(t,r){r.isRelationship&&e[r.kind].push(t)}),e}),relatedTypes:Ember.computed(function(){var t,r=Ember.A();return this.eachComputedProperty(function(n,i){i.isRelationship&&(t=i.type,"string"==typeof t&&(t=e(this,t,!1)||e(Ember.lookup,t)),r.contains(t)||r.push(t))}),r}),relationshipsByName:Ember.computed(function(){var e,t=Ember.Map.create();return this.eachComputedProperty(function(r,n){n.isRelationship&&(n.key=r,e=n.type,"string"==typeof e&&(n.type=this.store.modelFor(e)),t.set(r,n))}),t}),fields:Ember.computed(function(){var e=Ember.Map.create();return this.eachComputedProperty(function(t,r){r.isRelationship?e.set(t,r.kind):r.isAttribute&&e.set(t,"attribute")}),e}),eachRelationship:function(t,r){e(this,"relationshipsByName").forEach(function(e,n){t.call(r,e,n)})},eachRelatedType:function(t,r){e(this,"relatedTypes").forEach(function(e){t.call(r,e)})}}),DS.Model.reopen({eachRelationship:function(e,t){this.constructor.eachRelationship(e,t)}})}(),function(){var e=Ember.get;Ember.set;var t=Ember.run.once,r=Ember.EnumerableUtils.forEach;DS.RecordArrayManager=Ember.Object.extend({init:function(){this.filteredRecordArrays=Ember.MapWithDefault.create({defaultValue:function(){return[]}}),this.changedRecords=[]},recordDidChange:function(e){this.changedRecords.push(e),t(this,this.updateRecordArrays)},recordArraysForRecord:function(e){return e._recordArrays=e._recordArrays||Ember.OrderedSet.create(),e._recordArrays},updateRecordArrays:function(){r(this.changedRecords,function(t){var n,i=t.constructor,a=this.filteredRecordArrays.get(i);r(a,function(r){n=e(r,"filterFunction"),this.updateRecordArray(r,n,i,t)},this);var o=t._loadingRecordArrays;if(o){for(var s=0,c=o.length;c>s;s++)o[s].loadedRecord();t._loadingRecordArrays=[]}},this),this.changedRecords=[]},updateRecordArray:function(e,t,r,n){var i;i=t?t(n):!0;var a=this.recordArraysForRecord(n);i?(a.add(e),e.addRecord(n)):i||(a.remove(e),e.removeRecord(n))},remove:function(e){var t=e._recordArrays;t&&r(t,function(t){t.removeRecord(e)})},updateFilter:function(t,r,n){for(var i,a=this.store.typeMapFor(r),o=a.records,s=0,c=o.length;c>s;s++)i=o[s],e(i,"isDeleted")||e(i,"isEmpty")||this.updateRecordArray(t,n,r,i)},createManyArray:function(e,t){var n=DS.ManyArray.create({type:e,content:t,store:this.store});return r(t,function(e){var t=this.recordArraysForRecord(e);t.add(n)},this),n},registerFilteredRecordArray:function(e,t,r){var n=this.filteredRecordArrays.get(t);n.push(e),this.updateFilter(e,t,r)},registerWaitingRecordArray:function(e,t){var r=e._loadingRecordArrays||[];r.push(t),e._loadingRecordArrays=r}})}(),function(){var e=Ember.get;Ember.set,Ember.merge;var t=Ember.ArrayPolyfills.map;Ember.RSVP.resolve;var r=["description","fileName","lineNumber","message","name","number","stack"];DS.InvalidError=function(e){var t=Error.prototype.constructor.call(this,"The backend rejected the commit because it was invalid: "+Ember.inspect(e));this.errors=e;for(var n=0,i=r.length;i>n;n++)this[r[n]]=t[r[n]]},DS.InvalidError.prototype=Ember.create(Error.prototype),DS.Adapter=Ember.Object.extend(DS._Mappable,{find:Ember.required(Function),findAll:null,findQuery:null,generateIdForRecord:null,serialize:function(t,r){return e(t,"store").serializerFor(t.constructor.typeKey).serialize(t,r)},createRecord:Ember.required(Function),updateRecord:Ember.required(Function),deleteRecord:Ember.required(Function),findMany:function(e,r,n){var i=t.call(n,function(t){return this.find(e,r,t)},this);return Ember.RSVP.all(i)}})}(),function(){var e=Ember.get,t=Ember.String.fmt,r=Ember.EnumerableUtils.indexOf,n=0;DS.FixtureAdapter=DS.Adapter.extend({serializer:null,simulateRemoteResponse:!0,latency:50,fixturesForType:function(e){if(e.FIXTURES){var r=Ember.A(e.FIXTURES);return r.map(function(e){var r=typeof e.id;if("number"!==r&&"string"!==r)throw new Error(t("the id property must be defined as a number or string for fixture %@",[e]));return e.id=e.id+"",e})}return null},queryFixtures:function(){},updateFixtures:function(e,t){e.FIXTURES||(e.FIXTURES=[]);var r=e.FIXTURES;this.deleteLoadedFixture(e,t),r.push(t)},mockJSON:function(e,t,r){return e.serializerFor(t).serialize(r,{includeId:!0})},generateIdForRecord:function(){return n++},find:function(e,t,r){var n,i=this.fixturesForType(t);return i&&(n=Ember.A(i).findProperty("id",r)),n?this.simulateRemoteCall(function(){return n},this):void 0},findMany:function(e,t,n){var i=this.fixturesForType(t);return i&&(i=i.filter(function(e){return-1!==r(n,e.id)})),i?this.simulateRemoteCall(function(){return i},this):void 0},findAll:function(e,t){var r=this.fixturesForType(t);return this.simulateRemoteCall(function(){return r},this)},findQuery:function(e,t,r){var n=this.fixturesForType(t);return n=this.queryFixtures(n,r,t),n?this.simulateRemoteCall(function(){return n},this):void 0},createRecord:function(e,t,r){var n=this.mockJSON(e,t,r);return this.updateFixtures(t,n),this.simulateRemoteCall(function(){return n},this)},updateRecord:function(e,t,r){var n=this.mockJSON(e,t,r);return this.updateFixtures(t,n),this.simulateRemoteCall(function(){return n},this)},deleteRecord:function(e,t,r){var n=this.mockJSON(e,t,r);return this.deleteLoadedFixture(t,n),this.simulateRemoteCall(function(){return null})},deleteLoadedFixture:function(e,t){var n=this.findExistingFixture(e,t);if(n){var i=r(e.FIXTURES,n);return e.FIXTURES.splice(i,1),!0}},findExistingFixture:function(t,r){var n=this.fixturesForType(t),i=e(r,"id");return this.findFixtureById(n,i)},findFixtureById:function(t,r){return Ember.A(t).find(function(t){return""+e(t,"id")==""+r?!0:!1})},simulateRemoteCall:function(t,r){var n=this;return new Ember.RSVP.Promise(function(i){e(n,"simulateRemoteResponse")?Ember.run.later(function(){i(t.call(r))},e(n,"latency")):Ember.run.once(function(){i(t.call(r))})})}})}(),function(){function e(e){return null==e?null:e+""}var t=Ember.get;Ember.set;var r=Ember.ArrayPolyfills.forEach;DS.RESTSerializer=DS.JSONSerializer.extend({normalize:function(e,t,r){return this.normalizeId(t),this.normalizeUsingDeclaredMapping(e,t),this.normalizeAttributes(e,t),this.normalizeRelationships(e,t),this.normalizeHash&&this.normalizeHash[r]?this.normalizeHash[r](t):this._super(e,t,r)},normalizeId:function(e){var r=t(this,"primaryKey");"id"!==r&&(e.id=e[r],delete e[r])},normalizeUsingDeclaredMapping:function(e,r){var n,i,a=t(this,"attrs");if(a)for(i in a)n=a[i],r[i]=r[n],delete r[n]},normalizeAttributes:function(e,t){var r;this.keyForAttribute&&e.eachAttribute(function(e){r=this.keyForAttribute(e),e!==r&&(t[e]=t[r],delete t[r])},this)},normalizeRelationships:function(e,t){var r;this.keyForRelationship&&e.eachRelationship(function(e,n){r=this.keyForRelationship(e,n.kind),e!==r&&(t[e]=t[r],delete t[r])},this)},extractSingle:function(t,n,i,a){var o,s=n.typeKey;for(var c in i)if(c!==s){var d=this.singularize(c),u=t.modelFor(d);r.call(i[c],function(r){r=this.normalize(u,r,c);var n=d===s&&!a&&!o,i=d===s&&e(r.id)===a;n||i?o=r:t.push(d,r)},this)}else o=this.normalize(n,i[c],c);return o},extractArray:function(e,t,r){var n,i=t.typeKey;for(var a in r){var o=this.singularize(a),s=e.modelFor(o),c=o===i,d=r[a].map(function(e){return this.normalize(s,e,a)},this);c?n=d:e.pushMany(o,d)}return n},pluralize:function(e){return Ember.String.pluralize(e)},singularize:function(e){return Ember.String.singularize(e)},serialize:function(){return this._super.apply(this,arguments)}})}(),function(){var e=Ember.get;Ember.set;var t=Ember.ArrayPolyfills.forEach;DS.RESTAdapter=DS.Adapter.extend({defaultSerializer:"_rest",find:function(e,t,r){return this.ajax(this.buildURL(t.typeKey,r),"GET")},findAll:function(e,t,r){var n;return r&&(n={since:r}),this.ajax(this.buildURL(t.typeKey),"GET",{data:n})},findQuery:function(e,t,r){return this.ajax(this.buildURL(t.typeKey),"GET",{data:r})},findMany:function(e,t,r){return this.ajax(this.buildURL(t.typeKey),"GET",{data:{ids:r}})},findHasMany:function(e,t,r){return this.ajax(r,"GET")},createRecord:function(e,t,r){var n={};return n[t.typeKey]=e.serializerFor(t.typeKey).serialize(r,{includeId:!0}),this.ajax(this.buildURL(t.typeKey),"POST",{data:n})},updateRecord:function(t,r,n){var i={};i[r.typeKey]=t.serializerFor(r.typeKey).serialize(n);var a=e(n,"id");return this.ajax(this.buildURL(r.typeKey,a),"PUT",{data:i})},deleteRecord:function(t,r,n){var i=e(n,"id");return this.ajax(this.buildURL(r.typeKey,i),"DELETE")},buildURL:function(t,r){var n=e(this,"host"),i=e(this,"namespace"),a=[];return n&&a.push(n),i&&a.push(i),a.push(this.rootForType(t)),r&&a.push(r),a=a.join("/"),n||(a="/"+a),a},rootForType:function(e){return Ember.String.pluralize(e)},ajax:function(e,r,n){var i=this;return new Ember.RSVP.Promise(function(a,o){if(n=n||{},n.url=e,n.type=r,n.dataType="json",n.context=i,n.data&&"GET"!==r&&(n.contentType="application/json; charset=utf-8",n.data=JSON.stringify(n.data)),void 0!==i.headers){var s=i.headers;n.beforeSend=function(e){t.call(Ember.keys(s),function(t){e.setRequestHeader(t,s[t])})}}n.success=function(e){Ember.run(null,a,e)},n.error=function(e){e&&(e.then=null),Ember.run(null,o,e)},Ember.$.ajax(n)})}})}(),function(){DS.Model.reopen({_debugInfo:function(){var e=["id"],t={belongsTo:[],hasMany:[]},r=[];this.eachAttribute(function(t){e.push(t)},this),this.eachRelationship(function(e,n){t[n.kind].push(e),r.push(e)});var n=[{name:"Attributes",properties:e,expand:!0},{name:"Belongs To",properties:t.belongsTo,expand:!0},{name:"Has Many",properties:t.hasMany,expand:!0},{name:"Flags",properties:["isLoaded","isDirty","isSaving","isDeleted","isError","isNew","isValid"]}];return{propertyInfo:{includeOtherProperties:!0,groups:n,expensiveProperties:r}}}})}(),function(){Ember.String.pluralize=function(e){return Ember.Inflector.inflector.pluralize(e)},Ember.String.singularize=function(e){return Ember.Inflector.inflector.singularize(e)}}(),function(){function e(e,t){for(var r=0,n=t.length;n>r;r++)e.uncountable[t[r]]=!0}function t(e,t){for(var r,n=0,i=t.length;i>n;n++)r=t[n],e.irregular[r[0]]=r[1],e.irregularInverse[r[1]]=r[0]}function r(r){r=r||{},r.uncountable=r.uncountable||{},r.irregularPairs=r.irregularPairs||{};var n=this.rules={plurals:r.plurals||[],singular:r.singular||[],irregular:{},irregularInverse:{},uncountable:{}};e(n,r.uncountable),t(n,r.irregularPairs)}var n=/^\s*$/;r.prototype={pluralize:function(e){return this.inflect(e,this.rules.plurals)},singularize:function(e){return this.inflect(e,this.rules.singular)},inflect:function(e,t){var r,i,a,o,s,c,d,u,l;if(s=n.test(e))return e;if(o=e.toLowerCase(),c=this.rules.uncountable[o])return e;if(d=this.rules.irregular[o])return d;if(u=this.rules.irregularInverse[o])return u;for(var h=t.length,f=0;h>f&&(r=t[h-1],l=r[0],!l.test(e));h--);return r=r||[],l=r[0],i=r[1],a=e.replace(l,i)}},Ember.Inflector=r}(),function(){Ember.Inflector.defaultRules={plurals:[[/$/,"s"],[/s$/i,"s"],[/^(ax|test)is$/i,"$1es"],[/(octop|vir)us$/i,"$1i"],[/(octop|vir)i$/i,"$1i"],[/(alias|status)$/i,"$1es"],[/(bu)s$/i,"$1ses"],[/(buffal|tomat)o$/i,"$1oes"],[/([ti])um$/i,"$1a"],[/([ti])a$/i,"$1a"],[/sis$/i,"ses"],[/(?:([^f])fe|([lr])f)$/i,"$1$2ves"],[/(hive)$/i,"$1s"],[/([^aeiouy]|qu)y$/i,"$1ies"],[/(x|ch|ss|sh)$/i,"$1es"],[/(matr|vert|ind)(?:ix|ex)$/i,"$1ices"],[/^(m|l)ouse$/i,"$1ice"],[/^(m|l)ice$/i,"$1ice"],[/^(ox)$/i,"$1en"],[/^(oxen)$/i,"$1"],[/(quiz)$/i,"$1zes"]],singular:[[/s$/i,""],[/(ss)$/i,"$1"],[/(n)ews$/i,"$1ews"],[/([ti])a$/i,"$1um"],[/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)(sis|ses)$/i,"$1sis"],[/(^analy)(sis|ses)$/i,"$1sis"],[/([^f])ves$/i,"$1fe"],[/(hive)s$/i,"$1"],[/(tive)s$/i,"$1"],[/([lr])ves$/i,"$1f"],[/([^aeiouy]|qu)ies$/i,"$1y"],[/(s)eries$/i,"$1eries"],[/(m)ovies$/i,"$1ovie"],[/(x|ch|ss|sh)es$/i,"$1"],[/^(m|l)ice$/i,"$1ouse"],[/(bus)(es)?$/i,"$1"],[/(o)es$/i,"$1"],[/(shoe)s$/i,"$1"],[/(cris|test)(is|es)$/i,"$1is"],[/^(a)x[ie]s$/i,"$1xis"],[/(octop|vir)(us|i)$/i,"$1us"],[/(alias|status)(es)?$/i,"$1"],[/^(ox)en/i,"$1"],[/(vert|ind)ices$/i,"$1ex"],[/(matr)ices$/i,"$1ix"],[/(quiz)zes$/i,"$1"],[/(database)s$/i,"$1"]],irregularPairs:[["person","people"],["man","men"],["child","children"],["sex","sexes"],["move","moves"],["cow","kine"],["zombie","zombies"]],uncountable:["equipment","information","rice","money","species","series","fish","sheep","jeans","police"]}}(),function(){Ember.EXTEND_PROTOTYPES&&(String.prototype.pluralize=function(){return Ember.String.pluralize(this)},String.prototype.singularize=function(){return Ember.String.singularize(this)})}(),function(){Ember.Inflector.inflector=new Ember.Inflector(Ember.Inflector.defaultRules)}()}(),"undefined"==typeof location||"localhost"!==location.hostname&&"127.0.0.1"!==location.hostname||Ember.Logger.warn("You are running a production build of Ember on localhost and won't receive detailed error messages. If you want full error messages please use the non-minified build provided on the Ember website.");
14
+ // Copyright: Copyright 2011-2013 Tilde Inc. and contributors.
15
+ // Portions Copyright 2011 LivingSocial Inc.
16
+ !function(){var e,t;!function(){var r={},n={};e=function(e,t,n){r[e]={deps:t,callback:n}},t=function(e){if(n[e])return n[e];n[e]={};var i,a,o,s,c;if(i=r[e],!i)throw new Error("Module '"+e+"' not found.");a=i.deps,o=i.callback,s=[];for(var u=0,d=a.length;d>u;u++)"exports"===a[u]?s.push(c={}):s.push(t(a[u]));var l=o.apply(this,s);return n[e]=c||l}}(),function(){"undefined"==typeof DS&&(DS=Ember.Namespace.create({VERSION:"1.0.0-beta.2"}),"undefined"!=typeof window&&(window.DS=DS),Ember.libraries&&Ember.libraries.registerCoreLibrary("Ember Data",DS.VERSION))}(),function(){function e(e){return function(){return this[e].apply(this,arguments)}}var t=Ember.get,r=(Ember.set,Ember.isNone);DS.JSONSerializer=Ember.Object.extend({primaryKey:"id",applyTransforms:function(e,t){return e.eachTransformedAttribute(function(e,r){var n=this.transformFor(r);t[e]=n.deserialize(t[e])},this),t},normalize:function(e,t){return t?(this.applyTransforms(e,t),t):t},serialize:function(e,r){var n={};if(r&&r.includeId){var i=t(e,"id");i&&(n[t(this,"primaryKey")]=t(e,"id"))}return e.eachAttribute(function(t,r){this.serializeAttribute(e,n,t,r)},this),e.eachRelationship(function(t,r){"belongsTo"===r.kind?this.serializeBelongsTo(e,n,r):"hasMany"===r.kind&&this.serializeHasMany(e,n,r)},this),n},serializeAttribute:function(e,r,n,i){var a=t(this,"attrs"),o=t(e,n),s=i.type;if(s){var c=this.transformFor(s);o=c.serialize(o)}n=a&&a[n]||(this.keyForAttribute?this.keyForAttribute(n):n),r[n]=o},serializeBelongsTo:function(e,n,i){var a=i.key,o=t(e,a);a=this.keyForRelationship?this.keyForRelationship(a,"belongsTo"):a,n[a]=r(o)?o:t(o,"id"),i.options.polymorphic&&this.serializePolymorphicType(e,n,i)},serializeHasMany:function(e,r,n){var i=n.key,a=DS.RelationshipChange.determineRelationshipType(e.constructor,n);("manyToNone"===a||"manyToMany"===a)&&(r[i]=t(e,i).mapBy("id"))},serializePolymorphicType:Ember.K,extract:function(e,t,r,n,i){this.extractMeta(e,t,r);var a="extract"+i.charAt(0).toUpperCase()+i.substr(1);return this[a](e,t,r,n,i)},extractFindAll:e("extractArray"),extractFindQuery:e("extractArray"),extractFindMany:e("extractArray"),extractFindHasMany:e("extractArray"),extractCreateRecord:e("extractSave"),extractUpdateRecord:e("extractSave"),extractDeleteRecord:e("extractSave"),extractFind:e("extractSingle"),extractFindBelongsTo:e("extractSingle"),extractSave:e("extractSingle"),extractSingle:function(e,t,r){return this.normalize(t,r)},extractArray:function(e,t,r){return this.normalize(t,r)},extractMeta:function(e,t,r){r&&r.meta&&(e.metaForType(t,r.meta),delete r.meta)},transformFor:function(e){var t=this.container.lookup("transform:"+e);return t}})}(),function(){var e=Ember.get,t=Ember.String.capitalize,r=Ember.String.underscore,n=window.DS;n.DebugAdapter=Ember.DataAdapter.extend({getFilters:function(){return[{name:"isNew",desc:"New"},{name:"isModified",desc:"Modified"},{name:"isClean",desc:"Clean"}]},detect:function(e){return e!==n.Model&&n.Model.detect(e)},columnsForType:function(n){var i=[{name:"id",desc:"Id"}],a=0,o=this;return e(n,"attributes").forEach(function(e){if(a++>o.attributeLimit)return!1;var n=t(r(e).replace("_"," "));i.push({name:e,desc:n})}),i},getRecords:function(e){return this.get("store").all(e)},getRecordColumnValues:function(t){var r=this,n=0,i={id:e(t,"id")};return t.eachAttribute(function(a){if(n++>r.attributeLimit)return!1;var o=e(t,a);i[a]=o}),i},getRecordKeywords:function(t){var r=[],n=Ember.A(["id"]);return t.eachAttribute(function(e){n.push(e)}),n.forEach(function(n){r.push(e(t,n))}),r},getRecordFilterValues:function(e){return{isNew:e.get("isNew"),isModified:e.get("isDirty")&&!e.get("isNew"),isClean:!e.get("isDirty")}},getRecordColor:function(e){var t="black";return e.get("isNew")?t="green":e.get("isDirty")&&(t="blue"),t},observeRecord:function(e,t){var r=Ember.A(),n=this,i=Ember.A(["id","isNew","isDirty"]);e.eachAttribute(function(e){i.push(e)}),i.forEach(function(i){var a=function(){t(n.wrapRecord(e))};Ember.addObserver(e,i,a),r.push(function(){Ember.removeObserver(e,i,a)})});var a=function(){r.forEach(function(e){e()})};return a}})}(),function(){DS.Transform=Ember.Object.extend({serialize:Ember.required(),deserialize:Ember.required()})}(),function(){DS.BooleanTransform=DS.Transform.extend({deserialize:function(e){var t=typeof e;return"boolean"===t?e:"string"===t?null!==e.match(/^true$|^t$|^1$/i):"number"===t?1===e:!1},serialize:function(e){return Boolean(e)}})}(),function(){DS.DateTransform=DS.Transform.extend({deserialize:function(e){var t=typeof e;return"string"===t?new Date(Ember.Date.parse(e)):"number"===t?new Date(e):null===e||void 0===e?e:null},serialize:function(e){if(e instanceof Date){var t=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],r=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],n=function(e){return 10>e?"0"+e:""+e},i=e.getUTCFullYear(),a=e.getUTCMonth(),o=e.getUTCDate(),s=e.getUTCDay(),c=e.getUTCHours(),u=e.getUTCMinutes(),d=e.getUTCSeconds(),l=t[s],h=n(o),f=r[a];return l+", "+h+" "+f+" "+i+" "+n(c)+":"+n(u)+":"+n(d)+" GMT"}return null}})}(),function(){var e=Ember.isEmpty;DS.NumberTransform=DS.Transform.extend({deserialize:function(t){return e(t)?null:Number(t)},serialize:function(t){return e(t)?null:Number(t)}})}(),function(){var e=Ember.isNone;DS.StringTransform=DS.Transform.extend({deserialize:function(t){return e(t)?null:String(t)},serialize:function(t){return e(t)?null:String(t)}})}(),function(){Ember.set,Ember.onLoad("Ember.Application",function(e){e.initializer({name:"store",initialize:function(e,t){t.register("store:main",t.Store||DS.Store),t.register("serializer:_default",DS.JSONSerializer),t.register("serializer:_rest",DS.RESTSerializer),t.register("adapter:_rest",DS.RESTAdapter),e.lookup("store:main")}}),e.initializer({name:"transforms",initialize:function(e,t){t.register("transform:boolean",DS.BooleanTransform),t.register("transform:date",DS.DateTransform),t.register("transform:number",DS.NumberTransform),t.register("transform:string",DS.StringTransform)}}),e.initializer({name:"dataAdapter",initialize:function(e,t){t.register("dataAdapter:main",DS.DebugAdapter)}}),e.initializer({name:"injectStore",initialize:function(e,t){t.inject("controller","store","store:main"),t.inject("route","store","store:main"),t.inject("serializer","store","store:main"),t.inject("dataAdapter","store","store:main")}})})}(),function(){Ember.Date=Ember.Date||{};var e=Date.parse,t=[1,4,5,6,7,10,11];Ember.Date.parse=function(r){var n,i,a=0;if(i=/^(\d{4}|[+\-]\d{6})(?:-(\d{2})(?:-(\d{2}))?)?(?:T(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{3}))?)?(?:(Z)|([+\-])(\d{2})(?::(\d{2}))?)?)?$/.exec(r)){for(var o,s=0;o=t[s];++s)i[o]=+i[o]||0;i[2]=(+i[2]||1)-1,i[3]=+i[3]||1,"Z"!==i[8]&&void 0!==i[9]&&(a=60*i[10]+i[11],"+"===i[9]&&(a=0-a)),n=Date.UTC(i[1],i[2],i[3],i[4],i[5]+a,i[6],i[7])}else n=e?e(r):0/0;return n},(Ember.EXTEND_PROTOTYPES===!0||Ember.EXTEND_PROTOTYPES.Date)&&(Date.parse=Ember.Date.parse)}(),function(){var e=Ember.get;Ember.set,DS.RecordArray=Ember.ArrayProxy.extend(Ember.Evented,{type:null,content:null,isLoaded:!1,isUpdating:!1,store:null,objectAtContent:function(t){var r=e(this,"content");return r.objectAt(t)},update:function(){if(!e(this,"isUpdating")){var t=e(this,"store"),r=e(this,"type");t.fetchAll(r,this)}},addRecord:function(t){e(this,"content").addObject(t)},removeRecord:function(t){e(this,"content").removeObject(t)},save:function(){var e=Ember.RSVP.all(this.invoke("save")).then(function(e){return Ember.A(e)});return DS.PromiseArray.create({promise:e})}})}(),function(){var e=Ember.get;DS.FilteredRecordArray=DS.RecordArray.extend({filterFunction:null,isLoaded:!0,replace:function(){var t=e(this,"type").toString();throw new Error("The result of a client-side filter (on "+t+") is immutable.")},updateFilter:Ember.observer(function(){var t=e(this,"manager");t.updateFilter(this,e(this,"type"),e(this,"filterFunction"))},"filterFunction")})}(),function(){var e=Ember.get;Ember.set,DS.AdapterPopulatedRecordArray=DS.RecordArray.extend({query:null,replace:function(){var t=e(this,"type").toString();throw new Error("The result of a server query (on "+t+") is immutable.")},load:function(t){var r=e(this,"store"),n=e(this,"type"),i=r.pushMany(n,t),a=r.metadataFor(n);this.setProperties({content:Ember.A(i),isLoaded:!0,meta:a}),Ember.run.once(this,"trigger","didLoad")}})}(),function(){var e=Ember.get,t=Ember.set,r=Ember.EnumerableUtils.map;DS.ManyArray=DS.RecordArray.extend({init:function(){this._super.apply(this,arguments),this._changesToSync=Ember.OrderedSet.create()},owner:null,isPolymorphic:!1,isLoaded:!1,loadingRecordsCount:function(e){this.loadingRecordsCount=e},loadedRecord:function(){this.loadingRecordsCount--,0===this.loadingRecordsCount&&(t(this,"isLoaded",!0),this.trigger("didLoad"))},fetch:function(){var t=e(this,"content"),r=e(this,"store"),n=e(this,"owner"),i=Ember.RSVP.defer(),a=t.filterProperty("isEmpty",!0);r.fetchMany(a,n,i)},replaceContent:function(e,t,n){n=r(n,function(e){return e},this),this._super(e,t,n)},arrangedContentDidChange:function(){Ember.run.once(this,"fetch")},arrayContentWillChange:function(t,r){var n=e(this,"owner"),i=e(this,"name");if(!n._suspendedRelationships)for(var a=t;t+r>a;a++){var o=e(this,"content").objectAt(a),s=DS.RelationshipChange.createChange(n,o,e(this,"store"),{parentType:n.constructor,changeType:"remove",kind:"hasMany",key:i});this._changesToSync.add(s)}return this._super.apply(this,arguments)},arrayContentDidChange:function(t,r,n){this._super.apply(this,arguments);var i=e(this,"owner"),a=e(this,"name"),o=e(this,"store");if(!i._suspendedRelationships){for(var s=t;t+n>s;s++){var c=e(this,"content").objectAt(s),u=DS.RelationshipChange.createChange(i,c,o,{parentType:i.constructor,changeType:"add",kind:"hasMany",key:a});u.hasManyName=a,this._changesToSync.add(u)}this._changesToSync.forEach(function(e){e.sync()}),this._changesToSync.clear()}},createRecord:function(t){var r,n=e(this,"owner"),i=e(n,"store"),a=e(this,"type");return r=i.createRecord.call(i,a,t),this.pushObject(r),r}})}(),function(){function e(e){var t=Ember.meta(e,!0),r="DS.Mappable",n=t[r];return n||(t[r]={}),t.hasOwnProperty(r)||(t[r]=Ember.create(t[r])),t[r]}Ember.get;var t=Ember.ArrayPolyfills.forEach,r=function(e){return e},n=function(e){return e},i=function(e,t){return t};DS._Mappable=Ember.Mixin.create({createInstanceMapFor:function(t){var r=e(this);if(r.values=r.values||{},r.values[t])return r.values[t];for(var n=r.values[t]=new Ember.Map,i=this.constructor;i&&i!==DS.Store;)this._copyMap(t,i,n),i=i.superclass;return r.values[t]=n,n},_copyMap:function(a,o,s){function c(e,t){var a=(o.transformMapKey||n)(e,t),c=(o.transformMapValue||i)(e,t),u=s.get(a),d=c;u&&(d=(this.constructor.resolveMapConflict||r)(u,d)),s.set(a,d)}var u=e(o),d=u[a];d&&t.call(d,c,this)}}),DS._Mappable.generateMapFunctionFor=function(t,r){return function(n,i){var a=e(this),o=a[t]||Ember.MapWithDefault.create({defaultValue:function(){return{}}});r.call(this,n,i,o),a[t]=o}}}(),function(){function e(e,r,a,o){return r.eachRelationship(function(r,s){if(a.links&&a.links[r])return o&&s.options.async&&(o._relationships[r]=null),void 0;var c=s.kind,u=a[r];null!=u&&("belongsTo"===c?t(e,a,r,s,u):"hasMany"===c&&(n(e,a,r,s,u),i(o,r,u)))}),a}function t(e,t,n,i,a){if(!(v(a)||a instanceof DS.Model)){var o;"number"==typeof a||"string"==typeof a?(o=r(i,n,t),t[n]=e.recordForId(o,a)):"object"==typeof a&&(t[n]=e.recordForId(a.type,a.id))}}function r(e,t,r){return e.options.polymorphic?r[t+"Type"]:e.type}function n(e,r,n,i,a){for(var o=0,s=a.length;s>o;o++)t(e,a,o,i,a[o])}function i(e,t,r){e&&r.pushObjects(e.get(t).filterBy("isNew"))}function a(e){return DS.PromiseObject.create({promise:e})}function o(e){return DS.PromiseArray.create({promise:e})}function s(e,t,r){return e.lookup("serializer:"+t)||e.lookup("serializer:application")||e.lookup("serializer:"+r)||e.lookup("serializer:_default")}function c(e,t){var r=e.serializer,n=e.defaultSerializer,i=e.container;return i&&void 0===r&&(r=s(i,t.typeKey,n)),(null===r||void 0===r)&&(r={extract:function(e,t,r){return r}}),r}function u(e,t,r,n,i){var a=e.find(t,r,n),o=c(e,r);return D(a).then(function(e){return e=o.extract(t,r,e,n,"find"),t.push(r,e)},function(e){var i=t.getById(r,n);throw i.notFound(),e}).then(i.resolve,i.reject)}function d(e,t,r,n,i,a){var o=e.findMany(t,r,n,i),s=c(e,r);return D(o).then(function(e){e=s.extract(t,r,e,null,"findMany"),t.pushMany(r,e)}).then(a.resolve,a.reject)}function l(e,t,r,n,i,a){var o=e.findHasMany(t,r,n,i),s=c(e,i.type);return D(o).then(function(e){e=s.extract(t,i.type,e,null,"findHasMany");var n=t.pushMany(i.type,e);r.updateHasMany(i.key,n)}).then(a.resolve,a.reject)}function h(e,t,r,n,i,a){var o=e.findBelongsTo(t,r,n,i),s=c(e,i.type);return D(o).then(function(e){e=s.extract(t,i.type,e,null,"findBelongsTo");var r=t.push(i.type,e);return r.updateBelongsTo(i.key,r),r}).then(a.resolve,a.reject)}function f(e,t,r,n,i){var a=e.findAll(t,r,n),o=c(e,r);return D(a).then(function(e){return e=o.extract(t,r,e,null,"findAll"),t.pushMany(r,e),t.didUpdateAll(r),t.all(r)}).then(i.resolve,i.reject)}function p(e,t,r,n,i,a){var o=e.findQuery(t,r,n,i),s=c(e,r);return D(o).then(function(e){return e=s.extract(t,r,e,null,"findAll"),i.load(e),i}).then(a.resolve,a.reject)}function m(e,t,r,n,i){var a=n.constructor,o=e[r](t,a,n),s=c(e,a);return o.then(function(e){return e&&(e=s.extract(t,a,e,y(n,"id"),r)),t.didSaveRecord(n,e),n},function(e){throw e instanceof DS.InvalidError?t.recordWasInvalid(n,e.errors):t.recordWasError(n,e),e}).then(i.resolve,i.reject)}var y=Ember.get,g=Ember.set,b=Ember.run.once,v=Ember.isNone,R=Ember.EnumerableUtils.forEach,E=Ember.EnumerableUtils.indexOf,S=Ember.EnumerableUtils.map,D=Ember.RSVP.resolve,T=function(e){return null==e?null:e+""};DS.Store=Ember.Object.extend(DS._Mappable,{init:function(){this.typeMaps={},this.recordArrayManager=DS.RecordArrayManager.create({store:this}),this._relationshipChanges={},this._pendingSave=[]},adapter:"_rest",serialize:function(e,t){return this.serializerFor(e.constructor.typeKey).serialize(e,t)},defaultAdapter:Ember.computed(function(){var e=y(this,"adapter");return"string"==typeof e&&(e=this.container.lookup("adapter:"+e)||this.container.lookup("adapter:application")||this.container.lookup("adapter:_rest")),DS.Adapter.detect(e)&&(e=e.create({container:this.container})),e}).property("adapter"),createRecord:function(e,t){e=this.modelFor(e),t=t||{},v(t.id)&&(t.id=this._generateId(e)),t.id=T(t.id);var r=this.buildRecord(e,t.id);return r.loadedData(),r.setProperties(t),r},_generateId:function(e){var t=this.adapterFor(e);return t&&t.generateIdForRecord?t.generateIdForRecord(this):null},deleteRecord:function(e){e.deleteRecord()},unloadRecord:function(e){e.unloadRecord()},find:function(e,t){return void 0===t?this.findAll(e):"object"===Ember.typeOf(t)?this.findQuery(e,t):this.findById(e,T(t))},findById:function(e,t){e=this.modelFor(e);var r=this.recordForId(e,t),n=this.fetchRecord(r)||D(r);return a(n)},findByIds:function(e,t){var r=this;return o(Ember.RSVP.all(S(t,function(t){return r.findById(e,t)})).then(function(e){return Ember.A(e)}))},fetchRecord:function(e){if(v(e))return null;if(e._loadingPromise)return e._loadingPromise;if(!y(e,"isEmpty"))return null;var t=e.constructor,r=y(e,"id"),n=Ember.RSVP.defer();e.loadingData(n.promise);var i=this.adapterFor(t);return u(i,this,t,r,n),n.promise},getById:function(e,t){return e=this.modelFor(e),this.hasRecordForId(e,t)?this.recordForId(e,t):null},reloadRecord:function(e,t){var r=e.constructor,n=this.adapterFor(r),i=y(e,"id");return u(n,this,r,i,t)},fetchMany:function(e,t,r){if(e.length){var n=Ember.MapWithDefault.create({defaultValue:function(){return Ember.A()}});R(e,function(e){n.get(e.constructor).push(e)}),R(n,function(e,n){var i=n.mapProperty("id"),a=this.adapterFor(e);d(a,this,e,i,t,r)},this)}},hasRecordForId:function(e,t){return t=T(t),!!this.typeMapFor(e).idToRecord[t]},recordForId:function(e,t){e=this.modelFor(e),t=T(t);var r=this.typeMapFor(e).idToRecord[t];return r||(r=this.buildRecord(e,t)),r},findMany:function(e,t,r,n){r=this.modelFor(r),t=Ember.A(t);var i=t.filterProperty("isEmpty",!0),a=this.recordArrayManager.createManyArray(r,t);return R(i,function(e){e.loadingData()}),a.loadingRecordsCount=i.length,i.length?(R(i,function(e){this.recordArrayManager.registerWaitingRecordArray(e,a)},this),this.fetchMany(i,e,n)):(n&&n.resolve(),a.set("isLoaded",!0),Ember.run.once(a,"trigger","didLoad")),a},findHasMany:function(e,t,r,n){var i=this.adapterFor(e.constructor),a=this.recordArrayManager.createManyArray(r.type,Ember.A([]));return l(i,this,e,t,r,n),a},findBelongsTo:function(e,t,r,n){var i=this.adapterFor(e.constructor);h(i,this,e,t,r,n)},findQuery:function(e,t){e=this.modelFor(e);var r=DS.AdapterPopulatedRecordArray.create({type:e,query:t,content:Ember.A(),store:this}),n=this.adapterFor(e),i=Ember.RSVP.defer();return p(n,this,e,t,r,i),o(i.promise)},findAll:function(e){return e=this.modelFor(e),this.fetchAll(e,this.all(e))},fetchAll:function(e,t){var r=this.adapterFor(e),n=this.typeMapFor(e).metadata.since,i=Ember.RSVP.defer();return g(t,"isUpdating",!0),f(r,this,e,n,i),o(i.promise)},didUpdateAll:function(e){var t=this.typeMapFor(e).findAllCache;g(t,"isUpdating",!1)},all:function(e){e=this.modelFor(e);var t=this.typeMapFor(e),r=t.findAllCache;if(r)return r;var n=DS.RecordArray.create({type:e,content:Ember.A(),store:this,isLoaded:!0});return this.recordArrayManager.registerFilteredRecordArray(n,e),t.findAllCache=n,n},unloadAll:function(e){e=this.modelFor(e);for(var t,r=this.typeMapFor(e),n=r.records;t=n.pop();)t.unloadRecord()},filter:function(e,t,r){var n;3===arguments.length?n=this.findQuery(e,t):2===arguments.length&&(r=t),e=this.modelFor(e);var i=DS.FilteredRecordArray.create({type:e,content:Ember.A(),store:this,manager:this.recordArrayManager,filterFunction:r});return this.recordArrayManager.registerFilteredRecordArray(i,e,r),n?n.then(function(){return i}):i},recordIsLoaded:function(e,t){return this.hasRecordForId(e,t)?!y(this.recordForId(e,t),"isEmpty"):!1},metadataFor:function(e){return e=this.modelFor(e),this.typeMapFor(e).metadata},dataWasUpdated:function(e,t){y(t,"isDeleted")||y(t,"isLoaded")&&this.recordArrayManager.recordDidChange(t)},scheduleSave:function(e,t){e.adapterWillCommit(),this._pendingSave.push([e,t]),b(this,"flushPendingSave")},flushPendingSave:function(){var e=this._pendingSave.slice();this._pendingSave=[],R(e,function(e){var t,r=e[0],n=e[1],i=this.adapterFor(r.constructor);t=y(r,"isNew")?"createRecord":y(r,"isDeleted")?"deleteRecord":"updateRecord",m(i,this,t,r,n)},this)},didSaveRecord:function(t,r){r&&(r=e(this,t.constructor,r,t),this.updateId(t,r)),t.adapterDidCommit(r)},recordWasInvalid:function(e,t){e.adapterDidInvalidate(t)},recordWasError:function(e){e.adapterDidError()},updateId:function(e,t){var r=(y(e,"id"),T(t.id));this.typeMapFor(e.constructor).idToRecord[r]=e,g(e,"id",r)},typeMapFor:function(e){var t,r=y(this,"typeMaps"),n=Ember.guidFor(e);return(t=r[n])?t:(t={idToRecord:{},records:[],metadata:{}},r[n]=t,t)},_load:function(e,t,r){var n=T(t.id),i=this.recordForId(e,n);return i.setupData(t,r),this.recordArrayManager.recordDidChange(i),i},modelFor:function(e){var t;return"string"==typeof e?(t=this.container.lookupFactory("model:"+e),t.typeKey=e):t=e,t.store=this,t},push:function(t,r,n){return t=this.modelFor(t),r=e(this,t,r),this._load(t,r,n),this.recordForId(t,r.id)},pushPayload:function(e,t){var r=this.serializerFor(e);r.pushPayload(this,t)},update:function(e,t){return this.push(e,t,!0)},pushMany:function(e,t){return S(t,function(t){return this.push(e,t)},this)},metaForType:function(e,t){e=this.modelFor(e),Ember.merge(this.typeMapFor(e).metadata,t)},buildRecord:function(e,t,r){var n=this.typeMapFor(e),i=n.idToRecord,a=e._create({id:t,store:this,container:this.container});return r&&a.setupData(r),t&&(i[t]=a),n.records.push(a),a},dematerializeRecord:function(e){var t=e.constructor,r=this.typeMapFor(t),n=y(e,"id");e.updateRecordArrays(),n&&delete r.idToRecord[n];var i=E(r.records,e);r.records.splice(i,1)},addRelationshipChangeFor:function(e,t,r,n,i){var a=e.clientId,o=r?r:r,s=t+n,c=this._relationshipChanges;a in c||(c[a]={}),o in c[a]||(c[a][o]={}),s in c[a][o]||(c[a][o][s]={}),c[a][o][s][i.changeType]=i},removeRelationshipChangeFor:function(e,t,r,n,i){var a=e.clientId,o=r?r.clientId:r,s=this._relationshipChanges,c=t+n;a in s&&o in s[a]&&c in s[a][o]&&delete s[a][o][c][i]},relationshipChangePairsFor:function(e){var t=[];if(!e)return t;var r=this._relationshipChanges[e.clientId];for(var n in r)if(r.hasOwnProperty(n))for(var i in r[n])r[n].hasOwnProperty(i)&&t.push(r[n][i]);return t},adapterFor:function(e){var t,r=this.container;return r&&(t=r.lookup("adapter:"+e.typeKey)||r.lookup("adapter:application")),t||y(this,"defaultAdapter")},serializerFor:function(e){e=this.modelFor(e);var t=this.adapterFor(e);return s(this.container,e.typeKey,t&&t.defaultSerializer)}}),DS.PromiseArray=Ember.ArrayProxy.extend(Ember.PromiseProxyMixin),DS.PromiseObject=Ember.ObjectProxy.extend(Ember.PromiseProxyMixin)}(),function(){function e(t){var r,n={};for(var i in t)r=t[i],n[i]=r&&"object"==typeof r?e(r):r;return n}function t(e,t){for(var r in t)e[r]=t[r];return e}function r(r){var n=e(c);return t(n,r)}function n(e,r,i){e=t(r?Ember.create(r):{},e),e.parentState=r,e.stateName=i;for(var a in e)e.hasOwnProperty(a)&&"parentState"!==a&&"stateName"!==a&&"object"==typeof e[a]&&(e[a]=n(e[a],e,i+"."+a));return e}var i=Ember.get,a=Ember.set,o=function(e){var t,r,n,i=Ember.keys(e);for(t=0,r=i.length;r>t;t++)if(n=i[t],e.hasOwnProperty(n)&&e[n])return!0;return!1},s=function(e,t){t.value===t.originalValue?(delete e._attributes[t.name],e.send("propertyWasReset",t.name)):t.value!==t.oldValue&&e.send("becomeDirty"),e.updateRecordArraysLater()},c={initialState:"uncommitted",isDirty:!0,uncommitted:{didSetProperty:s,propertyWasReset:function(e){var t=!1;for(var r in e._attributes){t=!0;break}t||e.send("rolledBack")},pushedData:Ember.K,becomeDirty:Ember.K,willCommit:function(e){e.transitionTo("inFlight")},reloadRecord:function(e,t){i(e,"store").reloadRecord(e,t)},rolledBack:function(e){e.transitionTo("loaded.saved")},becameInvalid:function(e){e.transitionTo("invalid")},rollback:function(e){e.rollback()}},inFlight:{isSaving:!0,didSetProperty:s,becomeDirty:Ember.K,pushedData:Ember.K,willCommit:Ember.K,didCommit:function(e){var t=i(this,"dirtyType");e.transitionTo("saved"),e.send("invokeLifecycleCallbacks",t)},becameInvalid:function(e,t){a(e,"errors",t),e.transitionTo("invalid"),e.send("invokeLifecycleCallbacks")},becameError:function(e){e.transitionTo("uncommitted"),e.triggerLater("becameError",e)}},invalid:{isValid:!1,deleteRecord:function(e){e.transitionTo("deleted.uncommitted"),e.clearRelationships()},didSetProperty:function(e,t){var r=i(e,"errors"),n=t.name;a(r,n,null),o(r)||e.send("becameValid"),s(e,t)},becomeDirty:Ember.K,rollback:function(e){e.send("becameValid"),e.send("rollback")},becameValid:function(e){e.transitionTo("uncommitted")},invokeLifecycleCallbacks:function(e){e.triggerLater("becameInvalid",e)}}},u=r({dirtyType:"created",isNew:!0});u.uncommitted.rolledBack=function(e){e.transitionTo("deleted.saved")};var d=r({dirtyType:"updated"});u.uncommitted.deleteRecord=function(e){e.clearRelationships(),e.transitionTo("deleted.saved")},u.uncommitted.rollback=function(e){c.uncommitted.rollback.apply(this,arguments),e.transitionTo("deleted.saved")},d.uncommitted.deleteRecord=function(e){e.transitionTo("deleted.uncommitted"),e.clearRelationships()};var l={isEmpty:!1,isLoading:!1,isLoaded:!1,isDirty:!1,isSaving:!1,isDeleted:!1,isNew:!1,isValid:!0,rolledBack:Ember.K,propertyWasReset:Ember.K,empty:{isEmpty:!0,loadingData:function(e,t){e._loadingPromise=t,e.transitionTo("loading")},loadedData:function(e){e.transitionTo("loaded.created.uncommitted"),e.suspendRelationshipObservers(function(){e.notifyPropertyChange("data")})},pushedData:function(e){e.transitionTo("loaded.saved"),e.triggerLater("didLoad")}},loading:{isLoading:!0,exit:function(e){e._loadingPromise=null},pushedData:function(e){e.transitionTo("loaded.saved"),e.triggerLater("didLoad"),a(e,"isError",!1)},becameError:function(e){e.triggerLater("becameError",e)},notFound:function(e){e.transitionTo("empty")}},loaded:{initialState:"saved",isLoaded:!0,saved:{setup:function(e){var t=e._attributes,r=!1;for(var n in t)if(t.hasOwnProperty(n)){r=!0;break}r&&e.adapterDidDirty()},didSetProperty:s,pushedData:Ember.K,becomeDirty:function(e){e.transitionTo("updated.uncommitted")},willCommit:function(e){e.transitionTo("updated.inFlight")},reloadRecord:function(e,t){i(e,"store").reloadRecord(e,t)},deleteRecord:function(e){e.transitionTo("deleted.uncommitted"),e.clearRelationships()},unloadRecord:function(e){e.clearRelationships(),e.transitionTo("deleted.saved")},didCommit:function(e){e.send("invokeLifecycleCallbacks",i(e,"lastDirtyType"))}},created:u,updated:d},deleted:{initialState:"uncommitted",dirtyType:"deleted",isDeleted:!0,isLoaded:!0,isDirty:!0,setup:function(e){var t=i(e,"store");t.recordArrayManager.remove(e)},uncommitted:{willCommit:function(e){e.transitionTo("inFlight")},rollback:function(e){e.rollback()},becomeDirty:Ember.K,deleteRecord:Ember.K,rolledBack:function(e){e.transitionTo("loaded.saved")}},inFlight:{isSaving:!0,willCommit:Ember.K,didCommit:function(e){e.transitionTo("saved"),e.send("invokeLifecycleCallbacks")},becameError:function(e){e.transitionTo("uncommitted"),e.triggerLater("becameError",e)}},saved:{isDirty:!1,setup:function(e){var t=i(e,"store");t.dematerializeRecord(e)},invokeLifecycleCallbacks:function(e){e.triggerLater("didDelete",e),e.triggerLater("didCommit",e)}}},invokeLifecycleCallbacks:function(e,t){"created"===t?e.triggerLater("didCreate",e):e.triggerLater("didUpdate",e),e.triggerLater("didCommit",e)}};l=n(l,null,"root"),DS.RootState=l}(),function(){var e=Ember.get,t=Ember.set,r=Ember.merge,n=Ember.run.once,i=Ember.computed(function(t){return e(e(this,"currentState"),t)}).property("currentState").readOnly();DS.Model=Ember.Object.extend(Ember.Evented,{isEmpty:i,isLoading:i,isLoaded:i,isDirty:i,isSaving:i,isDeleted:i,isNew:i,isValid:i,dirtyType:i,isError:!1,isReloading:!1,clientId:null,id:null,transaction:null,currentState:null,errors:null,serialize:function(t){var r=e(this,"store");return r.serialize(this,t)},toJSON:function(e){var t=DS.JSONSerializer.create({container:this.container});return t.serialize(this,e)},didLoad:Ember.K,didReload:Ember.K,didUpdate:Ember.K,didCreate:Ember.K,didDelete:Ember.K,becameInvalid:Ember.K,becameError:Ember.K,data:Ember.computed(function(){return this._data=this._data||{},this._data}).property(),_data:null,init:function(){t(this,"currentState",DS.RootState.empty),this._super(),this._setup()},_setup:function(){this._changesToSync={},this._deferredTriggers=[],this._data={},this._attributes={},this._inFlightAttributes={},this._relationships={}},send:function(t,r){var n=e(this,"currentState");return n[t]||this._unhandledEvent(n,t,r),n[t](this,r)},transitionTo:function(r){var n=r.split(".",1),i=e(this,"currentState"),a=i;do a.exit&&a.exit(this),a=a.parentState;while(!a.hasOwnProperty(n));var o,s,c=r.split("."),u=[],d=[];for(o=0,s=c.length;s>o;o++)a=a[c[o]],a.enter&&d.push(a),a.setup&&u.push(a);for(o=0,s=d.length;s>o;o++)d[o].enter(this);for(t(this,"currentState",a),o=0,s=u.length;s>o;o++)u[o].setup(this);this.updateRecordArraysLater()},_unhandledEvent:function(e,t,r){var n="Attempted to handle event `"+t+"` ";throw n+="on "+String(this)+" while in state ",n+=e.stateName+". ",void 0!==r&&(n+="Called with "+Ember.inspect(r)+"."),new Ember.Error(n)},withTransaction:function(t){var r=e(this,"transaction");r&&t(r)},loadingData:function(e){this.send("loadingData",e)},loadedData:function(){this.send("loadedData")},notFound:function(){this.send("notFound")},pushedData:function(){this.send("pushedData")},deleteRecord:function(){this.send("deleteRecord")},destroyRecord:function(){return this.deleteRecord(),this.save()},unloadRecord:function(){this.send("unloadRecord")},clearRelationships:function(){this.eachRelationship(function(e,r){if("belongsTo"===r.kind)t(this,e,null);else if("hasMany"===r.kind){var n=this._relationships[r.name];n&&n.clear()}},this)},updateRecordArrays:function(){var t=e(this,"store");t&&t.dataWasUpdated(this.constructor,this)},changedAttributes:function(){var t,r=e(this,"_data"),n=e(this,"_attributes"),i={};for(t in n)i[t]=[r[t],n[t]];return i},adapterWillCommit:function(){this.send("willCommit")},adapterDidCommit:function(e){t(this,"isError",!1),e?this._data=e:Ember.mixin(this._data,this._inFlightAttributes),this._inFlightAttributes={},this.send("didCommit"),this.updateRecordArraysLater(),e&&this.suspendRelationshipObservers(function(){this.notifyPropertyChange("data")})},adapterDidDirty:function(){this.send("becomeDirty"),this.updateRecordArraysLater()},dataDidChange:Ember.observer(function(){this.reloadHasManys()},"data"),reloadHasManys:function(){var t=e(this.constructor,"relationshipsByName");this.updateRecordArraysLater(),t.forEach(function(e,t){this._data.links&&this._data.links[e]||"hasMany"===t.kind&&this.hasManyDidChange(t.key)},this)},hasManyDidChange:function(e){var r=this._relationships[e];if(r){var n=this._data[e]||[];t(r,"content",Ember.A(n)),t(r,"isLoaded",!0),r.trigger("didLoad")}},updateRecordArraysLater:function(){Ember.run.once(this,this.updateRecordArrays)},setupData:function(e,t){t?Ember.merge(this._data,e):this._data=e;var r=this._relationships;this.eachRelationship(function(t,n){e.links&&e.links[t]||n.options.async&&(r[t]=null)}),e&&this.pushedData(),this.suspendRelationshipObservers(function(){this.notifyPropertyChange("data")})},materializeId:function(e){t(this,"id",e)},materializeAttributes:function(e){r(this._data,e)},materializeAttribute:function(e,t){this._data[e]=t},updateHasMany:function(e,t){this._data[e]=t,this.hasManyDidChange(e)},updateBelongsTo:function(e,t){this._data[e]=t},rollback:function(){this._attributes={},e(this,"isError")&&(this._inFlightAttributes={},t(this,"isError",!1)),this.send("rolledBack"),this.suspendRelationshipObservers(function(){this.notifyPropertyChange("data")})},toStringExtension:function(){return e(this,"id")},suspendRelationshipObservers:function(t,r){var n=e(this.constructor,"relationshipNames").belongsTo,i=this;try{this._suspendedRelationships=!0,Ember._suspendObservers(i,n,null,"belongsToDidChange",function(){Ember._suspendBeforeObservers(i,n,null,"belongsToWillChange",function(){t.call(r||i)})})}finally{this._suspendedRelationships=!1}},save:function(){var e=Ember.RSVP.defer();return this.get("store").scheduleSave(this,e),this._inFlightAttributes=this._attributes,this._attributes={},DS.PromiseObject.create({promise:e.promise})},reload:function(){t(this,"isReloading",!0);var e=Ember.RSVP.defer(),r=this;return e.promise=e.promise.then(function(){return r.set("isReloading",!1),r.set("isError",!1),r},function(e){throw r.set("isError",!0),e}),this.send("reloadRecord",e),DS.PromiseObject.create({promise:e.promise})},adapterDidUpdateAttribute:function(e,t){void 0!==t?(this._data[e]=t,this.notifyPropertyChange(e)):this._data[e]=this._inFlightAttributes[e],this.updateRecordArraysLater()},adapterDidInvalidate:function(e){this.send("becameInvalid",e)},adapterDidError:function(){this.send("becameError"),t(this,"isError",!0)},trigger:function(e){Ember.tryInvoke(this,e,[].slice.call(arguments,1)),this._super.apply(this,arguments)},triggerLater:function(){this._deferredTriggers.push(arguments),n(this,"_triggerDeferredTriggers")},_triggerDeferredTriggers:function(){for(var e=0,t=this._deferredTriggers.length;t>e;e++)this.trigger.apply(this,this._deferredTriggers[e]);this._deferredTriggers=[]}}),DS.Model.reopenClass({_create:DS.Model.create,create:function(){throw new Ember.Error("You should not call `create` on a model. Instead, call `store.createRecord` with the attributes you would like to set.")}})}(),function(){function e(e,t){return"function"==typeof t.defaultValue?t.defaultValue():t.defaultValue}function t(e,t){return e._attributes.hasOwnProperty(t)||e._inFlightAttributes.hasOwnProperty(t)||e._data.hasOwnProperty(t)}function r(e,t){return e._attributes.hasOwnProperty(t)?e._attributes[t]:e._inFlightAttributes.hasOwnProperty(t)?e._inFlightAttributes[t]:e._data[t]}var n=Ember.get;DS.Model.reopenClass({attributes:Ember.computed(function(){var e=Ember.Map.create();return this.eachComputedProperty(function(t,r){r.isAttribute&&(r.name=t,e.set(t,r))}),e}),transformedAttributes:Ember.computed(function(){var e=Ember.Map.create();return this.eachAttribute(function(t,r){r.type&&e.set(t,r.type)}),e}),eachAttribute:function(e,t){n(this,"attributes").forEach(function(r,n){e.call(t,r,n)},t)},eachTransformedAttribute:function(e,t){n(this,"transformedAttributes").forEach(function(r,n){e.call(t,r,n)
17
+ })}}),DS.Model.reopen({eachAttribute:function(e,t){this.constructor.eachAttribute(e,t)}}),DS.attr=function(n,i){i=i||{};var a={type:n,isAttribute:!0,options:i};return Ember.computed(function(n,a){if(arguments.length>1){var o=this._attributes[n]||this._inFlightAttributes[n]||this._data[n];return this.send("didSetProperty",{name:n,oldValue:o,originalValue:this._data[n],value:a}),this._attributes[n]=a,a}return t(this,n)?r(this,n):e(this,i,n)}).property("data").meta(a)}}(),function(){var e=DS.AttributeChange=function(e){this.record=e.record,this.store=e.store,this.name=e.name,this.value=e.value,this.oldValue=e.oldValue};e.createChange=function(t){return new e(t)},e.prototype={sync:function(){this.value!==this.oldValue&&(this.record.send("becomeDirty"),this.record.updateRecordArraysLater()),this.destroy()},destroy:function(){delete this.record._changesToSync[this.name]}}}(),function(){function e(e){return"object"==typeof e&&(!e.then||"function"!=typeof e.then)}var t=Ember.get,r=Ember.set,n=Ember.EnumerableUtils.forEach;DS.RelationshipChange=function(e){this.parentRecord=e.parentRecord,this.childRecord=e.childRecord,this.firstRecord=e.firstRecord,this.firstRecordKind=e.firstRecordKind,this.firstRecordName=e.firstRecordName,this.secondRecord=e.secondRecord,this.secondRecordKind=e.secondRecordKind,this.secondRecordName=e.secondRecordName,this.changeType=e.changeType,this.store=e.store,this.committed={}},DS.RelationshipChangeAdd=function(e){DS.RelationshipChange.call(this,e)},DS.RelationshipChangeRemove=function(e){DS.RelationshipChange.call(this,e)},DS.RelationshipChange.create=function(e){return new DS.RelationshipChange(e)},DS.RelationshipChangeAdd.create=function(e){return new DS.RelationshipChangeAdd(e)},DS.RelationshipChangeRemove.create=function(e){return new DS.RelationshipChangeRemove(e)},DS.OneToManyChange={},DS.OneToNoneChange={},DS.ManyToNoneChange={},DS.OneToOneChange={},DS.ManyToManyChange={},DS.RelationshipChange._createChange=function(e){return"add"===e.changeType?DS.RelationshipChangeAdd.create(e):"remove"===e.changeType?DS.RelationshipChangeRemove.create(e):void 0},DS.RelationshipChange.determineRelationshipType=function(e,t){var r,n,i=t.key,a=t.kind,o=e.inverseFor(i);return o&&(r=o.name,n=o.kind),o?"belongsTo"===n?"belongsTo"===a?"oneToOne":"manyToOne":"belongsTo"===a?"oneToMany":"manyToMany":"belongsTo"===a?"oneToNone":"manyToNone"},DS.RelationshipChange.createChange=function(e,t,r,n){var i,a=e.constructor;return i=DS.RelationshipChange.determineRelationshipType(a,n),"oneToMany"===i?DS.OneToManyChange.createChange(e,t,r,n):"manyToOne"===i?DS.OneToManyChange.createChange(t,e,r,n):"oneToNone"===i?DS.OneToNoneChange.createChange(e,t,r,n):"manyToNone"===i?DS.ManyToNoneChange.createChange(e,t,r,n):"oneToOne"===i?DS.OneToOneChange.createChange(e,t,r,n):"manyToMany"===i?DS.ManyToManyChange.createChange(e,t,r,n):void 0},DS.OneToNoneChange.createChange=function(e,t,r,n){var i=n.key,a=DS.RelationshipChange._createChange({parentRecord:t,childRecord:e,firstRecord:e,store:r,changeType:n.changeType,firstRecordName:i,firstRecordKind:"belongsTo"});return r.addRelationshipChangeFor(e,i,t,null,a),a},DS.ManyToNoneChange.createChange=function(e,t,r,n){var i=n.key,a=DS.RelationshipChange._createChange({parentRecord:e,childRecord:t,secondRecord:e,store:r,changeType:n.changeType,secondRecordName:n.key,secondRecordKind:"hasMany"});return r.addRelationshipChangeFor(e,i,t,null,a),a},DS.ManyToManyChange.createChange=function(e,t,r,n){var i=n.key,a=DS.RelationshipChange._createChange({parentRecord:t,childRecord:e,firstRecord:e,secondRecord:t,firstRecordKind:"hasMany",secondRecordKind:"hasMany",store:r,changeType:n.changeType,firstRecordName:i});return r.addRelationshipChangeFor(e,i,t,null,a),a},DS.OneToOneChange.createChange=function(e,t,r,n){var i;n.parentType?i=n.parentType.inverseFor(n.key).name:n.key&&(i=n.key);var a=DS.RelationshipChange._createChange({parentRecord:t,childRecord:e,firstRecord:e,secondRecord:t,firstRecordKind:"belongsTo",secondRecordKind:"belongsTo",store:r,changeType:n.changeType,firstRecordName:i});return r.addRelationshipChangeFor(e,i,t,null,a),a},DS.OneToOneChange.maintainInvariant=function(e,r,n,i){if("add"===e.changeType&&r.recordIsMaterialized(n)){var a=t(n,i);if(a){var o=DS.OneToOneChange.createChange(n,a,r,{parentType:e.parentType,hasManyName:e.hasManyName,changeType:"remove",key:e.key});r.addRelationshipChangeFor(n,i,e.parentRecord,null,o),o.sync()}}},DS.OneToManyChange.createChange=function(e,t,r,n){var i;n.parentType?(i=n.parentType.inverseFor(n.key).name,DS.OneToManyChange.maintainInvariant(n,r,e,i)):n.key&&(i=n.key);var a=DS.RelationshipChange._createChange({parentRecord:t,childRecord:e,firstRecord:e,secondRecord:t,firstRecordKind:"belongsTo",secondRecordKind:"hasMany",store:r,changeType:n.changeType,firstRecordName:i});return r.addRelationshipChangeFor(e,i,t,a.getSecondRecordName(),a),a},DS.OneToManyChange.maintainInvariant=function(e,r,n,i){if("add"===e.changeType&&n){var a=t(n,i);if(a){var o=DS.OneToManyChange.createChange(n,a,r,{parentType:e.parentType,hasManyName:e.hasManyName,changeType:"remove",key:e.key});r.addRelationshipChangeFor(n,i,e.parentRecord,o.getSecondRecordName(),o),o.sync()}}},DS.RelationshipChange.prototype={getSecondRecordName:function(){var e,t=this.secondRecordName;if(!t){if(e=this.secondRecord,!e)return;var r=this.firstRecord.constructor,n=r.inverseFor(this.firstRecordName);this.secondRecordName=n.name}return this.secondRecordName},getFirstRecordName:function(){var e=this.firstRecordName;return e},destroy:function(){var e=this.childRecord,t=this.getFirstRecordName(),r=this.getSecondRecordName(),n=this.store;n.removeRelationshipChangeFor(e,t,this.parentRecord,r,this.changeType)},getSecondRecord:function(){return this.secondRecord},getFirstRecord:function(){return this.firstRecord},coalesce:function(){var e=this.store.relationshipChangePairsFor(this.firstRecord);n(e,function(e){var t=e.add,r=e.remove;t&&r&&(t.destroy(),r.destroy())})}},DS.RelationshipChangeAdd.prototype=Ember.create(DS.RelationshipChange.create({})),DS.RelationshipChangeRemove.prototype=Ember.create(DS.RelationshipChange.create({})),DS.RelationshipChangeAdd.prototype.changeType="add",DS.RelationshipChangeAdd.prototype.sync=function(){var n=this.getSecondRecordName(),i=this.getFirstRecordName(),a=this.getFirstRecord(),o=this.getSecondRecord();o instanceof DS.Model&&a instanceof DS.Model&&("belongsTo"===this.secondRecordKind?o.suspendRelationshipObservers(function(){r(o,n,a)}):"hasMany"===this.secondRecordKind&&o.suspendRelationshipObservers(function(){var r=t(o,n);e(r)&&r.addObject(a)})),a instanceof DS.Model&&o instanceof DS.Model&&t(a,i)!==o&&("belongsTo"===this.firstRecordKind?a.suspendRelationshipObservers(function(){r(a,i,o)}):"hasMany"===this.firstRecordKind&&a.suspendRelationshipObservers(function(){var r=t(a,i);e(r)&&r.addObject(o)})),this.coalesce()},DS.RelationshipChangeRemove.prototype.changeType="remove",DS.RelationshipChangeRemove.prototype.sync=function(){var n=this.getSecondRecordName(),i=this.getFirstRecordName(),a=this.getFirstRecord(),o=this.getSecondRecord();o instanceof DS.Model&&a instanceof DS.Model&&("belongsTo"===this.secondRecordKind?o.suspendRelationshipObservers(function(){r(o,n,null)}):"hasMany"===this.secondRecordKind&&o.suspendRelationshipObservers(function(){var r=t(o,n);e(r)&&r.removeObject(a)})),a instanceof DS.Model&&t(a,i)&&("belongsTo"===this.firstRecordKind?a.suspendRelationshipObservers(function(){r(a,i,null)}):"hasMany"===this.firstRecordKind&&a.suspendRelationshipObservers(function(){var r=t(a,i);e(r)&&r.removeObject(o)})),this.coalesce()}}(),function(){function e(e,n,i){return Ember.computed(function(e,n){var a=t(this,"data"),o=t(this,"store");if(2===arguments.length)return void 0===n?null:DS.PromiseObject.create({promise:Ember.RSVP.resolve(n)});var s=a.links&&a.links[e],c=a[e];if(r(c)){if(s){var u=Ember.RSVP.defer();return o.findBelongsTo(this,s,i,u),DS.PromiseObject.create({promise:u.promise})}return null}var d=o.fetchRecord(c)||Ember.RSVP.resolve(c);return DS.PromiseObject.create({promise:d})}).property("data").meta(i)}var t=Ember.get,r=(Ember.set,Ember.isNone);DS.belongsTo=function(n,i){"object"==typeof n&&(i=n,n=void 0),i=i||{};var a={type:n,isRelationship:!0,options:i,kind:"belongsTo"};return i.async?e(n,i,a):Ember.computed(function(e,i){var a,o,s=t(this,"data"),c=t(this,"store");return o="string"==typeof n?c.modelFor(n):n,2===arguments.length?void 0===i?null:i:(a=s[e],r(a)?null:(c.fetchRecord(a),a))}).property("data").meta(a)},DS.Model.reopen({belongsToWillChange:Ember.beforeObserver(function(e,r){if(t(e,"isLoaded")){var n=t(e,r);if(n){var i=t(e,"store"),a=DS.RelationshipChange.createChange(e,n,i,{key:r,kind:"belongsTo",changeType:"remove"});a.sync(),this._changesToSync[r]=a}}}),belongsToDidChange:Ember.immediateObserver(function(e,r){if(t(e,"isLoaded")){var n=t(e,r);if(n){var i=t(e,"store"),a=DS.RelationshipChange.createChange(e,n,i,{key:r,kind:"belongsTo",changeType:"add"});a.sync()}}delete this._changesToSync[r]})})}(),function(){function e(e,r,n){return Ember.computed(function(e){if(this._relationships[e])return this._relationships[e];var i=Ember.RSVP.defer(),a=t(this,e,r,function(t,r){var a=r.links&&r.links[e];return a?t.findHasMany(this,a,n,i):t.findMany(this,r[e],n.type,i)}),o=i.promise.then(function(){return a});return DS.PromiseArray.create({promise:o})}).property("data").meta(n)}function t(e,t,r,a){var o=e._relationships;if(o[t])return o[t];var s=n(e,"data"),c=n(e,"store"),u=o[t]=a.call(e,c,s);return i(u,{owner:e,name:t,isPolymorphic:r.polymorphic})}function r(r,n){n=n||{};var i={type:r,isRelationship:!0,options:n,kind:"hasMany"};return n.async?e(r,n,i):Ember.computed(function(e){return t(this,e,n,function(t,r){return r[e],t.findMany(this,r[e],i.type)})}).property("data").meta(i)}var n=Ember.get,i=(Ember.set,Ember.setProperties);DS.hasMany=function(e,t){return"object"==typeof e&&(t=e,e=void 0),r(e,t)}}(),function(){var e=Ember.get;Ember.set,DS.Model.reopen({didDefineProperty:function(e,t,r){if(r instanceof Ember.Descriptor){var n=r.meta();n.isRelationship&&"belongsTo"===n.kind&&(Ember.addObserver(e,t,null,"belongsToDidChange"),Ember.addBeforeObserver(e,t,null,"belongsToWillChange")),n.parentType=e.constructor}}}),DS.Model.reopenClass({typeForRelationship:function(t){var r=e(this,"relationshipsByName").get(t);return r&&r.type},inverseFor:function(t){function r(t,n,i){i=i||[];var a=e(n,"relationships");if(a){var o=a.get(t);return o&&i.push.apply(i,a.get(t)),t.superclass&&r(t.superclass,n,i),i}}var n=this.typeForRelationship(t);if(!n)return null;var i=this.metaForProperty(t).options;if(null===i.inverse)return null;var a,o;if(i.inverse)a=i.inverse,o=Ember.get(n,"relationshipsByName").get(a).kind;else{var s=r(this,n);if(0===s.length)return null;a=s[0].name,o=s[0].kind}return{type:n,name:a,kind:o}},relationships:Ember.computed(function(){var e=new Ember.MapWithDefault({defaultValue:function(){return[]}});return this.eachComputedProperty(function(t,r){if(r.isRelationship){"string"==typeof r.type&&(r.type=this.store.modelFor(r.type));var n=e.get(r.type);n.push({name:t,kind:r.kind})}}),e}),relationshipNames:Ember.computed(function(){var e={hasMany:[],belongsTo:[]};return this.eachComputedProperty(function(t,r){r.isRelationship&&e[r.kind].push(t)}),e}),relatedTypes:Ember.computed(function(){var t,r=Ember.A();return this.eachComputedProperty(function(n,i){i.isRelationship&&(t=i.type,"string"==typeof t&&(t=e(this,t,!1)||this.store.modelFor(t)),r.contains(t)||r.push(t))}),r}),relationshipsByName:Ember.computed(function(){var e,t=Ember.Map.create();return this.eachComputedProperty(function(r,n){n.isRelationship&&(n.key=r,e=n.type,e||"hasMany"!==n.kind?e||(e=r):e=Ember.String.singularize(r),"string"==typeof e&&(n.type=this.store.modelFor(e)),t.set(r,n))}),t}),fields:Ember.computed(function(){var e=Ember.Map.create();return this.eachComputedProperty(function(t,r){r.isRelationship?e.set(t,r.kind):r.isAttribute&&e.set(t,"attribute")}),e}),eachRelationship:function(t,r){e(this,"relationshipsByName").forEach(function(e,n){t.call(r,e,n)})},eachRelatedType:function(t,r){e(this,"relatedTypes").forEach(function(e){t.call(r,e)})}}),DS.Model.reopen({eachRelationship:function(e,t){this.constructor.eachRelationship(e,t)}})}(),function(){var e=Ember.get;Ember.set;var t=Ember.run.once,r=Ember.EnumerableUtils.forEach;DS.RecordArrayManager=Ember.Object.extend({init:function(){this.filteredRecordArrays=Ember.MapWithDefault.create({defaultValue:function(){return[]}}),this.changedRecords=[]},recordDidChange:function(e){this.changedRecords.push(e),t(this,this.updateRecordArrays)},recordArraysForRecord:function(e){return e._recordArrays=e._recordArrays||Ember.OrderedSet.create(),e._recordArrays},updateRecordArrays:function(){r(this.changedRecords,function(t){var n,i=t.constructor,a=this.filteredRecordArrays.get(i);r(a,function(r){n=e(r,"filterFunction"),this.updateRecordArray(r,n,i,t)},this);var o=t._loadingRecordArrays;if(o){for(var s=0,c=o.length;c>s;s++)o[s].loadedRecord();t._loadingRecordArrays=[]}},this),this.changedRecords=[]},updateRecordArray:function(e,t,r,n){var i;i=t?t(n):!0;var a=this.recordArraysForRecord(n);i?(a.add(e),e.addRecord(n)):i||(a.remove(e),e.removeRecord(n))},remove:function(e){var t=e._recordArrays;t&&r(t,function(t){t.removeRecord(e)})},updateFilter:function(t,r,n){for(var i,a=this.store.typeMapFor(r),o=a.records,s=0,c=o.length;c>s;s++)i=o[s],e(i,"isDeleted")||e(i,"isEmpty")||this.updateRecordArray(t,n,r,i)},createManyArray:function(e,t){var n=DS.ManyArray.create({type:e,content:t,store:this.store});return r(t,function(e){var t=this.recordArraysForRecord(e);t.add(n)},this),n},registerFilteredRecordArray:function(e,t,r){var n=this.filteredRecordArrays.get(t);n.push(e),this.updateFilter(e,t,r)},registerWaitingRecordArray:function(e,t){var r=e._loadingRecordArrays||[];r.push(t),e._loadingRecordArrays=r}})}(),function(){var e=Ember.get;Ember.set;var t=Ember.ArrayPolyfills.map,r=["description","fileName","lineNumber","message","name","number","stack"];DS.InvalidError=function(e){var t=Error.prototype.constructor.call(this,"The backend rejected the commit because it was invalid: "+Ember.inspect(e));this.errors=e;for(var n=0,i=r.length;i>n;n++)this[r[n]]=t[r[n]]},DS.InvalidError.prototype=Ember.create(Error.prototype),DS.Adapter=Ember.Object.extend(DS._Mappable,{find:Ember.required(Function),findAll:null,findQuery:null,generateIdForRecord:null,serialize:function(t,r){return e(t,"store").serializerFor(t.constructor.typeKey).serialize(t,r)},createRecord:Ember.required(Function),updateRecord:Ember.required(Function),deleteRecord:Ember.required(Function),findMany:function(e,r,n){var i=t.call(n,function(t){return this.find(e,r,t)},this);return Ember.RSVP.all(i)}})}(),function(){var e=Ember.get,t=Ember.String.fmt,r=Ember.EnumerableUtils.indexOf,n=0;DS.FixtureAdapter=DS.Adapter.extend({serializer:null,simulateRemoteResponse:!0,latency:50,fixturesForType:function(e){if(e.FIXTURES){var r=Ember.A(e.FIXTURES);return r.map(function(e){var r=typeof e.id;if("number"!==r&&"string"!==r)throw new Error(t("the id property must be defined as a number or string for fixture %@",[e]));return e.id=e.id+"",e})}return null},queryFixtures:function(){},updateFixtures:function(e,t){e.FIXTURES||(e.FIXTURES=[]);var r=e.FIXTURES;this.deleteLoadedFixture(e,t),r.push(t)},mockJSON:function(e,t,r){return e.serializerFor(t).serialize(r,{includeId:!0})},generateIdForRecord:function(){return"fixture-"+n++},find:function(e,t,r){var n,i=this.fixturesForType(t);return i&&(n=Ember.A(i).findProperty("id",r)),n?this.simulateRemoteCall(function(){return n},this):void 0},findMany:function(e,t,n){var i=this.fixturesForType(t);return i&&(i=i.filter(function(e){return-1!==r(n,e.id)})),i?this.simulateRemoteCall(function(){return i},this):void 0},findAll:function(e,t){var r=this.fixturesForType(t);return this.simulateRemoteCall(function(){return r},this)},findQuery:function(e,t,r){var n=this.fixturesForType(t);return n=this.queryFixtures(n,r,t),n?this.simulateRemoteCall(function(){return n},this):void 0},createRecord:function(e,t,r){var n=this.mockJSON(e,t,r);return this.updateFixtures(t,n),this.simulateRemoteCall(function(){return n},this)},updateRecord:function(e,t,r){var n=this.mockJSON(e,t,r);return this.updateFixtures(t,n),this.simulateRemoteCall(function(){return n},this)},deleteRecord:function(e,t,r){var n=this.mockJSON(e,t,r);return this.deleteLoadedFixture(t,n),this.simulateRemoteCall(function(){return null})},deleteLoadedFixture:function(e,t){var n=this.findExistingFixture(e,t);if(n){var i=r(e.FIXTURES,n);return e.FIXTURES.splice(i,1),!0}},findExistingFixture:function(t,r){var n=this.fixturesForType(t),i=e(r,"id");return this.findFixtureById(n,i)},findFixtureById:function(t,r){return Ember.A(t).find(function(t){return""+e(t,"id")==""+r?!0:!1})},simulateRemoteCall:function(t,r){var n=this;return new Ember.RSVP.Promise(function(i){e(n,"simulateRemoteResponse")?Ember.run.later(function(){i(t.call(r))},e(n,"latency")):Ember.run.once(function(){i(t.call(r))})})}})}(),function(){function e(e){return null==e?null:e+""}var t=Ember.get;Ember.set;var r=Ember.ArrayPolyfills.forEach,n=Ember.ArrayPolyfills.map;DS.RESTSerializer=DS.JSONSerializer.extend({normalize:function(e,t,r){return this.normalizeId(t),this.normalizeUsingDeclaredMapping(e,t),this.normalizeAttributes(e,t),this.normalizeRelationships(e,t),this.normalizeHash&&this.normalizeHash[r]?this.normalizeHash[r](t):this._super(e,t,r)},normalizePayload:function(e,t){return t},normalizeId:function(e){var r=t(this,"primaryKey");"id"!==r&&(e.id=e[r],delete e[r])},normalizeUsingDeclaredMapping:function(e,r){var n,i,a=t(this,"attrs");if(a)for(i in a)n=a[i],r[i]=r[n],delete r[n]},normalizeAttributes:function(e,t){var r;this.keyForAttribute&&e.eachAttribute(function(e){r=this.keyForAttribute(e),e!==r&&(t[e]=t[r],delete t[r])},this)},normalizeRelationships:function(e,t){var r;this.keyForRelationship&&e.eachRelationship(function(e,n){r=this.keyForRelationship(e,n.kind),e!==r&&(t[e]=t[r],delete t[r])},this)},extractSingle:function(t,n,i,a){i=this.normalizePayload(n,i);var o,s=n.typeKey;for(var c in i){var u=this.typeForRoot(c),d=u===s;d&&"array"!==Ember.typeOf(i[c])?o=this.normalize(n,i[c],c):(t.modelFor(u),r.call(i[c],function(r){var n=this.typeForRoot(c),i=t.modelFor(n),s=t.serializerFor(i);r=s.normalize(i,r,c);var u=d&&!a&&!o,l=d&&e(r.id)===a;u||l?o=r:t.push(n,r)},this))}return o},extractArray:function(e,t,r){r=this.normalizePayload(t,r);var i,a=t.typeKey;for(var o in r){var s=o,c=!1;"_"===o.charAt(0)&&(c=!0,s=o.substr(1));var u=this.typeForRoot(s),d=e.modelFor(u),l=e.serializerFor(d),h=!c&&u===a,f=n.call(r[o],function(e){return l.normalize(d,e,o)},this);h?i=f:e.pushMany(u,f)}return i},pushPayload:function(e,t){t=this.normalizePayload(null,t);for(var r in t){var i=this.typeForRoot(r),a=e.modelFor(i),o=n.call(t[r],function(e){return this.normalize(a,e,r)},this);e.pushMany(i,o)}},typeForRoot:function(e){return Ember.String.singularize(e)},serialize:function(){return this._super.apply(this,arguments)},serializeIntoHash:function(e,t,r,n){e[t.typeKey]=this.serialize(r,n)},serializePolymorphicType:function(e,r,n){var i=n.key,a=t(e,i);i=this.keyForAttribute?this.keyForAttribute(i):i,r[i+"Type"]=a.constructor.typeKey}})}(),function(){var e=Ember.get;Ember.set;var t=Ember.ArrayPolyfills.forEach;DS.RESTAdapter=DS.Adapter.extend({defaultSerializer:"_rest",find:function(e,t,r){return this.ajax(this.buildURL(t.typeKey,r),"GET")},findAll:function(e,t,r){var n;return r&&(n={since:r}),this.ajax(this.buildURL(t.typeKey),"GET",{data:n})},findQuery:function(e,t,r){return this.ajax(this.buildURL(t.typeKey),"GET",{data:r})},findMany:function(e,t,r){return this.ajax(this.buildURL(t.typeKey),"GET",{data:{ids:r}})},findHasMany:function(t,r,n){var i=e(this,"host"),a=e(r,"id"),o=r.constructor.typeKey;return i&&"/"===n.charAt(0)&&"/"!==n.charAt(1)&&(n=i+n),this.ajax(this.urlPrefix(n,this.buildURL(o,a)),"GET")},findBelongsTo:function(t,r,n){var i=e(r,"id"),a=r.constructor.typeKey;return this.ajax(this.urlPrefix(n,this.buildURL(a,i)),"GET")},createRecord:function(e,t,r){var n={},i=e.serializerFor(t.typeKey);return i.serializeIntoHash(n,t,r,{includeId:!0}),this.ajax(this.buildURL(t.typeKey),"POST",{data:n})},updateRecord:function(t,r,n){var i={},a=t.serializerFor(r.typeKey);a.serializeIntoHash(i,r,n);var o=e(n,"id");return this.ajax(this.buildURL(r.typeKey,o),"PUT",{data:i})},deleteRecord:function(t,r,n){var i=e(n,"id");return this.ajax(this.buildURL(r.typeKey,i),"DELETE")},buildURL:function(t,r){var n=[],i=e(this,"host"),a=this.urlPrefix();return t&&n.push(this.pathForType(t)),r&&n.push(r),a&&n.unshift(a),n=n.join("/"),!i&&n&&(n="/"+n),n},urlPrefix:function(t,r){var n=e(this,"host"),i=e(this,"namespace"),a=[];return t?"/"===t.charAt(0)?n&&(t=t.slice(1),a.push(n)):/^http(s)?:\/\//.test(t)||a.push(r):(n&&a.push(n),i&&a.push(i)),t&&a.push(t),a.join("/")},pathForType:function(e){return Ember.String.pluralize(e)},ajaxError:function(e){return e&&(e.then=null),e},ajax:function(e,t,r){var n=this;return new Ember.RSVP.Promise(function(i,a){r=n.ajaxOptions(e,t,r),r.success=function(e){Ember.run(null,i,e)},r.error=function(e){Ember.run(null,a,n.ajaxError(e))},Ember.$.ajax(r)})},ajaxOptions:function(e,r,n){if(n=n||{},n.url=e,n.type=r,n.dataType="json",n.context=this,n.data&&"GET"!==r&&(n.contentType="application/json; charset=utf-8",n.data=JSON.stringify(n.data)),void 0!==this.headers){var i=this.headers;n.beforeSend=function(e){t.call(Ember.keys(i),function(t){e.setRequestHeader(t,i[t])})}}return n}})}(),function(){DS.Model.reopen({_debugInfo:function(){var e=["id"],t={belongsTo:[],hasMany:[]},r=[];this.eachAttribute(function(t){e.push(t)},this),this.eachRelationship(function(e,n){t[n.kind].push(e),r.push(e)});var n=[{name:"Attributes",properties:e,expand:!0},{name:"Belongs To",properties:t.belongsTo,expand:!0},{name:"Has Many",properties:t.hasMany,expand:!0},{name:"Flags",properties:["isLoaded","isDirty","isSaving","isDeleted","isError","isNew","isValid"]}];return{propertyInfo:{includeOtherProperties:!0,groups:n,expensiveProperties:r}}}})}(),function(){Ember.String.pluralize=function(e){return Ember.Inflector.inflector.pluralize(e)},Ember.String.singularize=function(e){return Ember.Inflector.inflector.singularize(e)}}(),function(){function e(e,t){for(var r=0,n=t.length;n>r;r++)e.uncountable[t[r]]=!0}function t(e,t){for(var r,n=0,i=t.length;i>n;n++)r=t[n],e.irregular[r[0]]=r[1],e.irregularInverse[r[1]]=r[0]}function r(r){r=r||{},r.uncountable=r.uncountable||{},r.irregularPairs=r.irregularPairs||{};var n=this.rules={plurals:r.plurals||[],singular:r.singular||[],irregular:{},irregularInverse:{},uncountable:{}};e(n,r.uncountable),t(n,r.irregularPairs)}var n=/^\s*$/;r.prototype={plural:function(e,t){this.rules.plurals.push([e,t])},singular:function(e,t){this.rules.singular.push([e,t])},uncountable:function(t){e(this.rules,[t])},irregular:function(e,r){t(this.rules,[[e,r]])},pluralize:function(e){return this.inflect(e,this.rules.plurals,this.rules.irregular)},singularize:function(e){return this.inflect(e,this.rules.singular,this.rules.irregularInverse)},inflect:function(e,t,r){var i,a,o,s,c,u,d,l;if(c=n.test(e))return e;if(s=e.toLowerCase(),u=this.rules.uncountable[s])return e;if(d=r&&r[s])return d;for(var h=t.length,f=0;h>f&&(i=t[h-1],l=i[0],!l.test(e));h--);return i=i||[],l=i[0],a=i[1],o=e.replace(l,a)}},Ember.Inflector=r}(),function(){Ember.Inflector.defaultRules={plurals:[[/$/,"s"],[/s$/i,"s"],[/^(ax|test)is$/i,"$1es"],[/(octop|vir)us$/i,"$1i"],[/(octop|vir)i$/i,"$1i"],[/(alias|status)$/i,"$1es"],[/(bu)s$/i,"$1ses"],[/(buffal|tomat)o$/i,"$1oes"],[/([ti])um$/i,"$1a"],[/([ti])a$/i,"$1a"],[/sis$/i,"ses"],[/(?:([^f])fe|([lr])f)$/i,"$1$2ves"],[/(hive)$/i,"$1s"],[/([^aeiouy]|qu)y$/i,"$1ies"],[/(x|ch|ss|sh)$/i,"$1es"],[/(matr|vert|ind)(?:ix|ex)$/i,"$1ices"],[/^(m|l)ouse$/i,"$1ice"],[/^(m|l)ice$/i,"$1ice"],[/^(ox)$/i,"$1en"],[/^(oxen)$/i,"$1"],[/(quiz)$/i,"$1zes"]],singular:[[/s$/i,""],[/(ss)$/i,"$1"],[/(n)ews$/i,"$1ews"],[/([ti])a$/i,"$1um"],[/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)(sis|ses)$/i,"$1sis"],[/(^analy)(sis|ses)$/i,"$1sis"],[/([^f])ves$/i,"$1fe"],[/(hive)s$/i,"$1"],[/(tive)s$/i,"$1"],[/([lr])ves$/i,"$1f"],[/([^aeiouy]|qu)ies$/i,"$1y"],[/(s)eries$/i,"$1eries"],[/(m)ovies$/i,"$1ovie"],[/(x|ch|ss|sh)es$/i,"$1"],[/^(m|l)ice$/i,"$1ouse"],[/(bus)(es)?$/i,"$1"],[/(o)es$/i,"$1"],[/(shoe)s$/i,"$1"],[/(cris|test)(is|es)$/i,"$1is"],[/^(a)x[ie]s$/i,"$1xis"],[/(octop|vir)(us|i)$/i,"$1us"],[/(alias|status)(es)?$/i,"$1"],[/^(ox)en/i,"$1"],[/(vert|ind)ices$/i,"$1ex"],[/(matr)ices$/i,"$1ix"],[/(quiz)zes$/i,"$1"],[/(database)s$/i,"$1"]],irregularPairs:[["person","people"],["man","men"],["child","children"],["sex","sexes"],["move","moves"],["cow","kine"],["zombie","zombies"]],uncountable:["equipment","information","rice","money","species","series","fish","sheep","jeans","police"]}}(),function(){(Ember.EXTEND_PROTOTYPES===!0||Ember.EXTEND_PROTOTYPES.String)&&(String.prototype.pluralize=function(){return Ember.String.pluralize(this)},String.prototype.singularize=function(){return Ember.String.singularize(this)})}(),function(){Ember.Inflector.inflector=new Ember.Inflector(Ember.Inflector.defaultRules)}(),function(){function e(n,i,a,o,s){var c=t(i,"attrs");c&&a.eachRelationship(function(i,a){var u,d,l,h,f=c[i],p=n.serializerFor(a.type.typeKey),m=t(p,"primaryKey");if("hasMany"===a.kind&&f&&("always"===f.embedded||"load"===f.embedded)){if(d="_"+Ember.String.pluralize(a.type.typeKey),u=this.keyForRelationship(i,a.kind),l=this.keyForAttribute(i),h=[],!o[l])return;s[d]=s[d]||[],r(o[l],function(t){var r=n.modelFor(a.type.typeKey);e(n,p,r,t,s),h.push(t[m]),s[d].push(t)}),o[u]=h,delete o[l]}},i)}var t=Ember.get,r=Ember.EnumerableUtils.forEach;DS.ActiveModelSerializer=DS.RESTSerializer.extend({keyForAttribute:function(e){return Ember.String.decamelize(e)},keyForRelationship:function(e,t){return e=Ember.String.decamelize(e),"belongsTo"===t?e+"_id":"hasMany"===t?Ember.String.singularize(e)+"_ids":e},serializeHasMany:function(e,r,n){var i=n.key,a=t(this,"attrs"),o=a&&a[i]&&"always"===a[i].embedded;o&&(r[this.keyForAttribute(i)]=t(e,i).map(function(e){var r=e.serialize(),n=t(this,"primaryKey");return r[n]=t(e,n),r},this))},serializeIntoHash:function(e,t,r,n){var i=Ember.String.decamelize(t.typeKey);e[i]=this.serialize(r,n)},serializePolymorphicType:function(e,r,n){var i=n.key,a=t(e,i);i=this.keyForAttribute(i),r[i+"_type"]=Ember.String.capitalize(a.constructor.typeKey)},typeForRoot:function(e){var t=Ember.String.camelize(e);return Ember.String.singularize(t)},normalizeRelationships:function(e,t){var n,i;this.keyForRelationship&&e.eachRelationship(function(e,a){if(a.options.polymorphic){if(n=this.keyForAttribute(e),i=t[n],i&&i.type)i.type=this.typeForRoot(i.type);else if(i&&"hasMany"===a.kind){var o=this;r(i,function(e){e.type=o.typeForRoot(e.type)})}}else n=this.keyForRelationship(e,a.kind),i=t[n];t[e]=i,e!==n&&delete t[n]},this)},extractSingle:function(t,r,n,i,a){var o=this.keyForAttribute(r.typeKey),s=n[o];return e(t,this,r,s,n),this._super(t,r,n,i,a)},extractArray:function(t,n,i){var a=this.keyForAttribute(n.typeKey),o=i[Ember.String.pluralize(a)];return r(o,function(r){e(t,this,n,r,i)},this),this._super(t,n,i)}})}(),function(){var e=Ember.EnumerableUtils.forEach;DS.ActiveModelAdapter=DS.RESTAdapter.extend({defaultSerializer:"_ams",pathForType:function(e){var t=Ember.String.decamelize(e);return Ember.String.pluralize(t)},ajaxError:function(t){var r=this._super(t);if(t&&422===t.status){var n=Ember.$.parseJSON(t.responseText).errors,i={};return e(Ember.keys(n),function(e){i[Ember.String.camelize(e)]=n[e]}),new DS.InvalidError(i)}return r}})}(),function(){Ember.onLoad("Ember.Application",function(e){e.initializer({name:"activeModelAdapter",initialize:function(e,t){t.register("serializer:_ams",DS.ActiveModelSerializer),t.register("adapter:_ams",DS.ActiveModelAdapter)}})})}()}(),"undefined"==typeof location||"localhost"!==location.hostname&&"127.0.0.1"!==location.hostname||Ember.Logger.warn("You are running a production build of Ember on localhost and won't receive detailed error messages. If you want full error messages please use the non-minified build provided on the Ember website.");
@@ -1,3 +1,16 @@
1
+ // ==========================================================================
2
+ // Project: Ember Data
3
+ // Copyright: Copyright 2011-2013 Tilde Inc. and contributors.
4
+ // Portions Copyright 2011 LivingSocial Inc.
5
+ // License: Licensed under MIT license (see license.js)
6
+ // ==========================================================================
7
+
8
+
9
+
10
+ // Version: v1.0.0-beta.3-48-gb47afef
11
+ // Last commit: b47afef (2013-10-08 19:07:59 -0700)
12
+
13
+
1
14
  (function() {
2
15
  var define, requireModule;
3
16
 
@@ -51,12 +64,16 @@ var define, requireModule;
51
64
 
52
65
  if ('undefined' === typeof DS) {
53
66
  DS = Ember.Namespace.create({
54
- VERSION: '1.0.0-beta.1'
67
+ VERSION: '1.0.0-beta.2'
55
68
  });
56
69
 
57
70
  if ('undefined' !== typeof window) {
58
71
  window.DS = DS;
59
72
  }
73
+
74
+ if (Ember.libraries) {
75
+ Ember.libraries.registerCoreLibrary('Ember Data', DS.VERSION);
76
+ }
60
77
  }
61
78
  })();
62
79
 
@@ -95,8 +112,6 @@ DS.JSONSerializer = Ember.Object.extend({
95
112
  // SERIALIZE
96
113
 
97
114
  serialize: function(record, options) {
98
- var store = get(this, 'store');
99
-
100
115
  var json = {};
101
116
 
102
117
  if (options && options.includeId) {
@@ -133,7 +148,7 @@ DS.JSONSerializer = Ember.Object.extend({
133
148
 
134
149
  // if provided, use the mapping provided by `attrs` in
135
150
  // the serializer
136
- key = attrs && attrs[key] || key;
151
+ key = attrs && attrs[key] || (this.keyForAttribute ? this.keyForAttribute(key) : key);
137
152
 
138
153
  json[key] = value;
139
154
  },
@@ -143,12 +158,16 @@ DS.JSONSerializer = Ember.Object.extend({
143
158
 
144
159
  var belongsTo = get(record, key);
145
160
 
146
- if (isNone(belongsTo)) { return; }
161
+ key = this.keyForRelationship ? this.keyForRelationship(key, "belongsTo") : key;
147
162
 
148
- json[key] = get(belongsTo, 'id');
163
+ if (isNone(belongsTo)) {
164
+ json[key] = belongsTo;
165
+ } else {
166
+ json[key] = get(belongsTo, 'id');
167
+ }
149
168
 
150
169
  if (relationship.options.polymorphic) {
151
- json[key + "_type"] = belongsTo.constructor.typeKey;
170
+ this.serializePolymorphicType(record, json, relationship);
152
171
  }
153
172
  },
154
173
 
@@ -163,6 +182,11 @@ DS.JSONSerializer = Ember.Object.extend({
163
182
  }
164
183
  },
165
184
 
185
+ /**
186
+ You can use this method to customize how polymorphic objects are serialized.
187
+ */
188
+ serializePolymorphicType: Ember.K,
189
+
166
190
  // EXTRACT
167
191
 
168
192
  extract: function(store, type, payload, id, requestType) {
@@ -182,6 +206,7 @@ DS.JSONSerializer = Ember.Object.extend({
182
206
  extractDeleteRecord: aliasMethod('extractSave'),
183
207
 
184
208
  extractFind: aliasMethod('extractSingle'),
209
+ extractFindBelongsTo: aliasMethod('extractSingle'),
185
210
  extractSave: aliasMethod('extractSingle'),
186
211
 
187
212
  extractSingle: function(store, type, payload) {
@@ -201,16 +226,10 @@ DS.JSONSerializer = Ember.Object.extend({
201
226
 
202
227
  // HELPERS
203
228
 
204
- typeFor: function(relationship, key, data) {
205
- if (relationship.options.polymorphic) {
206
- return data[key + "_type"];
207
- } else {
208
- return relationship.type;
209
- }
210
- },
229
+ transformFor: function(attributeType, skipAssertion) {
230
+ var transform = this.container.lookup('transform:' + attributeType);
211
231
 
212
- transformFor: function(attributeType) {
213
- return this.container.lookup('transform:' + attributeType);
232
+ return transform;
214
233
  }
215
234
  });
216
235
 
@@ -226,6 +245,11 @@ var get = Ember.get, capitalize = Ember.String.capitalize, underscore = Ember.St
226
245
 
227
246
  /**
228
247
  Extend `Ember.DataAdapter` with ED specific code.
248
+
249
+ @class DebugAdapter
250
+ @namespace DS
251
+ @extends Ember.DataAdapter
252
+ @private
229
253
  */
230
254
  DS.DebugAdapter = Ember.DataAdapter.extend({
231
255
  getFilters: function() {
@@ -242,7 +266,7 @@ DS.DebugAdapter = Ember.DataAdapter.extend({
242
266
 
243
267
  columnsForType: function(type) {
244
268
  var columns = [{ name: 'id', desc: 'Id' }], count = 0, self = this;
245
- Ember.A(get(type, 'attributes')).forEach(function(name, meta) {
269
+ get(type, 'attributes').forEach(function(name, meta) {
246
270
  if (count++ > self.attributeLimit) { return false; }
247
271
  var desc = capitalize(underscore(name).replace('_', ' '));
248
272
  columns.push({ name: name, desc: desc });
@@ -438,7 +462,7 @@ DS.NumberTransform = DS.Transform.extend({
438
462
 
439
463
 
440
464
  (function() {
441
- var none = Ember.isNone, empty = Ember.isEmpty;
465
+ var none = Ember.isNone;
442
466
 
443
467
  DS.StringTransform = DS.Transform.extend({
444
468
 
@@ -451,6 +475,7 @@ DS.StringTransform = DS.Transform.extend({
451
475
  }
452
476
 
453
477
  });
478
+
454
479
  })();
455
480
 
456
481
 
@@ -684,6 +709,14 @@ DS.RecordArray = Ember.ArrayProxy.extend(Ember.Evented, {
684
709
 
685
710
  removeRecord: function(record) {
686
711
  get(this, 'content').removeObject(record);
712
+ },
713
+
714
+ save: function() {
715
+ var promise = Ember.RSVP.all(this.invoke("save")).then(function(array) {
716
+ return Ember.A(array);
717
+ });
718
+
719
+ return DS.PromiseArray.create({ promise: promise });
687
720
  }
688
721
  });
689
722
 
@@ -745,11 +778,13 @@ DS.AdapterPopulatedRecordArray = DS.RecordArray.extend({
745
778
  load: function(data) {
746
779
  var store = get(this, 'store'),
747
780
  type = get(this, 'type'),
748
- records = store.pushMany(type, data);
781
+ records = store.pushMany(type, data),
782
+ meta = store.metadataFor(type);
749
783
 
750
784
  this.setProperties({
751
785
  content: Ember.A(records),
752
- isLoaded: true
786
+ isLoaded: true,
787
+ meta: meta
753
788
  });
754
789
 
755
790
  // TODO: does triggering didLoad event should be the last action of the runLoop?
@@ -783,11 +818,11 @@ var map = Ember.EnumerableUtils.map;
783
818
  defined:
784
819
 
785
820
  App.Post = DS.Model.extend({
786
- comments: DS.hasMany('App.Comment')
821
+ comments: DS.hasMany('comment')
787
822
  });
788
823
 
789
824
  App.Comment = DS.Model.extend({
790
- post: DS.belongsTo('App.Post')
825
+ post: DS.belongsTo('post')
791
826
  });
792
827
 
793
828
  If you created a new instance of `App.Post` and added
@@ -844,10 +879,11 @@ DS.ManyArray = DS.RecordArray.extend({
844
879
  fetch: function() {
845
880
  var records = get(this, 'content'),
846
881
  store = get(this, 'store'),
847
- owner = get(this, 'owner');
882
+ owner = get(this, 'owner'),
883
+ resolver = Ember.RSVP.defer();
848
884
 
849
885
  var unloadedRecords = records.filterProperty('isEmpty', true);
850
- store.fetchMany(unloadedRecords, owner);
886
+ store.fetchMany(unloadedRecords, owner, resolver);
851
887
  },
852
888
 
853
889
  // Overrides Ember.Array's replace method to implement
@@ -862,7 +898,7 @@ DS.ManyArray = DS.RecordArray.extend({
862
898
  },
863
899
 
864
900
  arrangedContentDidChange: function() {
865
- this.fetch();
901
+ Ember.run.once(this, 'fetch');
866
902
  },
867
903
 
868
904
  arrayContentWillChange: function(index, removed, added) {
@@ -1131,7 +1167,6 @@ var isNone = Ember.isNone;
1131
1167
  var forEach = Ember.EnumerableUtils.forEach;
1132
1168
  var indexOf = Ember.EnumerableUtils.indexOf;
1133
1169
  var map = Ember.EnumerableUtils.map;
1134
- var OrderedSet = Ember.OrderedSet;
1135
1170
  var resolve = Ember.RSVP.resolve;
1136
1171
 
1137
1172
  // Implementors Note:
@@ -1341,7 +1376,7 @@ DS.Store = Ember.Object.extend(DS._Mappable, {
1341
1376
  @returns String if the adapter can generate one, an ID
1342
1377
  */
1343
1378
  _generateId: function(type) {
1344
- var adapter = this.adapterForType(type);
1379
+ var adapter = this.adapterFor(type);
1345
1380
 
1346
1381
  if (adapter && adapter.generateIdForRecord) {
1347
1382
  return adapter.generateIdForRecord(this);
@@ -1445,12 +1480,10 @@ DS.Store = Ember.Object.extend(DS._Mappable, {
1445
1480
  findById: function(type, id) {
1446
1481
  type = this.modelFor(type);
1447
1482
 
1448
- var record = this.getById(type, id);
1449
- if (get(record, 'isEmpty')) {
1450
- return promiseObject(this.fetchRecord(record));
1451
- } else {
1452
- return promiseObject(resolve(record));
1453
- }
1483
+ var record = this.recordForId(type, id);
1484
+
1485
+ var promise = this.fetchRecord(record) || resolve(record);
1486
+ return promiseObject(promise);
1454
1487
  },
1455
1488
 
1456
1489
  /**
@@ -1483,13 +1516,17 @@ DS.Store = Ember.Object.extend(DS._Mappable, {
1483
1516
  @returns Promise
1484
1517
  */
1485
1518
  fetchRecord: function(record) {
1519
+ if (isNone(record)) { return null; }
1520
+ if (record._loadingPromise) { return record._loadingPromise; }
1521
+ if (!get(record, 'isEmpty')) { return null; }
1522
+
1486
1523
  var type = record.constructor,
1487
1524
  id = get(record, 'id'),
1488
1525
  resolver = Ember.RSVP.defer();
1489
1526
 
1490
- record.loadingData();
1527
+ record.loadingData(resolver.promise);
1491
1528
 
1492
- var adapter = this.adapterForType(type);
1529
+ var adapter = this.adapterFor(type);
1493
1530
 
1494
1531
 
1495
1532
 
@@ -1502,7 +1539,7 @@ DS.Store = Ember.Object.extend(DS._Mappable, {
1502
1539
  Get a record by a given type and ID without triggering a fetch.
1503
1540
 
1504
1541
  This method will synchronously return the record if it's available.
1505
- Otherwise, it will return undefined.
1542
+ Otherwise, it will return null.
1506
1543
 
1507
1544
  ```js
1508
1545
  var post = store.getById('post', 1);
@@ -1518,7 +1555,7 @@ DS.Store = Ember.Object.extend(DS._Mappable, {
1518
1555
  if (this.hasRecordForId(type, id)) {
1519
1556
  return this.recordForId(type, id);
1520
1557
  } else {
1521
- return this.buildRecord(type, id);
1558
+ return null;
1522
1559
  }
1523
1560
  },
1524
1561
 
@@ -1537,8 +1574,7 @@ DS.Store = Ember.Object.extend(DS._Mappable, {
1537
1574
  */
1538
1575
  reloadRecord: function(record, resolver) {
1539
1576
  var type = record.constructor,
1540
- adapter = this.adapterForType(type),
1541
- store = this,
1577
+ adapter = this.adapterFor(type),
1542
1578
  id = get(record, 'id');
1543
1579
 
1544
1580
 
@@ -1578,7 +1614,7 @@ DS.Store = Ember.Object.extend(DS._Mappable, {
1578
1614
 
1579
1615
  forEach(recordsByTypeMap, function(type, records) {
1580
1616
  var ids = records.mapProperty('id'),
1581
- adapter = this.adapterForType(type);
1617
+ adapter = this.adapterFor(type);
1582
1618
 
1583
1619
 
1584
1620
 
@@ -1589,7 +1625,8 @@ DS.Store = Ember.Object.extend(DS._Mappable, {
1589
1625
  /**
1590
1626
  Returns true if a record for a given type and ID is already loaded.
1591
1627
 
1592
- @param {String} type
1628
+ @method hasRecordForId
1629
+ @param {DS.Model} type
1593
1630
  @param {String|Integer} id
1594
1631
  @returns Boolean
1595
1632
  */
@@ -1603,6 +1640,7 @@ DS.Store = Ember.Object.extend(DS._Mappable, {
1603
1640
  Returns id record for a given type and ID. If one isn't already loaded,
1604
1641
  it builds a new record and leaves it in the `empty` state.
1605
1642
 
1643
+ @method recordForId
1606
1644
  @param {String} type
1607
1645
  @param {String|Integer} id
1608
1646
  @returns DS.Model
@@ -1670,6 +1708,7 @@ DS.Store = Ember.Object.extend(DS._Mappable, {
1670
1708
  The usual use-case is for the server to register a URL as a link, and
1671
1709
  then use that URL in the future to make a request for the relationship.
1672
1710
 
1711
+ @method findHasMany
1673
1712
  @private
1674
1713
  @param {DS.Model} owner
1675
1714
  @param {any} link
@@ -1678,7 +1717,7 @@ DS.Store = Ember.Object.extend(DS._Mappable, {
1678
1717
  @return DS.ManyArray
1679
1718
  */
1680
1719
  findHasMany: function(owner, link, relationship, resolver) {
1681
- var adapter = this.adapterForType(owner.constructor);
1720
+ var adapter = this.adapterFor(owner.constructor);
1682
1721
 
1683
1722
 
1684
1723
 
@@ -1687,6 +1726,14 @@ DS.Store = Ember.Object.extend(DS._Mappable, {
1687
1726
  return records;
1688
1727
  },
1689
1728
 
1729
+ findBelongsTo: function(owner, link, relationship, resolver) {
1730
+ var adapter = this.adapterFor(owner.constructor);
1731
+
1732
+
1733
+
1734
+ _findBelongsTo(adapter, this, owner, link, relationship, resolver);
1735
+ },
1736
+
1690
1737
  /**
1691
1738
  This method delegates a query to the adapter. This is the one place where
1692
1739
  adapter-level semantics are exposed to the application.
@@ -1714,7 +1761,7 @@ DS.Store = Ember.Object.extend(DS._Mappable, {
1714
1761
  store: this
1715
1762
  });
1716
1763
 
1717
- var adapter = this.adapterForType(type),
1764
+ var adapter = this.adapterFor(type),
1718
1765
  resolver = Ember.RSVP.defer();
1719
1766
 
1720
1767
 
@@ -1748,7 +1795,7 @@ DS.Store = Ember.Object.extend(DS._Mappable, {
1748
1795
  @returns Promise
1749
1796
  */
1750
1797
  fetchAll: function(type, array) {
1751
- var adapter = this.adapterForType(type),
1798
+ var adapter = this.adapterFor(type),
1752
1799
  sinceToken = this.typeMapFor(type).metadata.since,
1753
1800
  resolver = Ember.RSVP.defer();
1754
1801
 
@@ -1805,6 +1852,24 @@ DS.Store = Ember.Object.extend(DS._Mappable, {
1805
1852
  return array;
1806
1853
  },
1807
1854
 
1855
+
1856
+ /**
1857
+ This method unloads all of the known records for a given type.
1858
+
1859
+ @method unloadAll
1860
+ @param {Class} type
1861
+ */
1862
+ unloadAll: function(type) {
1863
+ type = this.modelFor(type);
1864
+
1865
+ var typeMap = this.typeMapFor(type),
1866
+ records = typeMap.records, record;
1867
+
1868
+ while(record = records.pop()) {
1869
+ record.unloadRecord();
1870
+ }
1871
+ },
1872
+
1808
1873
  /**
1809
1874
  Takes a type and filter function, and returns a live RecordArray that
1810
1875
  remains up to date as new records are loaded into the store or created
@@ -1821,14 +1886,6 @@ DS.Store = Ember.Object.extend(DS._Mappable, {
1821
1886
  filter function will be invoked again to determine whether it should
1822
1887
  still be in the array.
1823
1888
 
1824
- Note that the existence of a filter on a type will trigger immediate
1825
- materialization of all loaded data for a given type, so you might
1826
- not want to use filters for a type if you are loading many records
1827
- into the store, many of which are not active at any given time.
1828
-
1829
- In this scenario, you might want to consider filtering the raw
1830
- data before loading it into the store.
1831
-
1832
1889
  @method filter
1833
1890
  @param {Class} type
1834
1891
  @param {Function} filter
@@ -1878,6 +1935,18 @@ DS.Store = Ember.Object.extend(DS._Mappable, {
1878
1935
  return !get(this.recordForId(type, id), 'isEmpty');
1879
1936
  },
1880
1937
 
1938
+ /**
1939
+ This method returns the metadata for a specific type.
1940
+
1941
+ @method metadataFor
1942
+ @param {string} type
1943
+ @return {object}
1944
+ */
1945
+ metadataFor: function(type) {
1946
+ type = this.modelFor(type);
1947
+ return this.typeMapFor(type).metadata;
1948
+ },
1949
+
1881
1950
  // ............
1882
1951
  // . UPDATING .
1883
1952
  // ............
@@ -1947,7 +2016,7 @@ DS.Store = Ember.Object.extend(DS._Mappable, {
1947
2016
 
1948
2017
  forEach(pending, function(tuple) {
1949
2018
  var record = tuple[0], resolver = tuple[1],
1950
- adapter = this.adapterForType(record.constructor),
2019
+ adapter = this.adapterFor(record.constructor),
1951
2020
  operation;
1952
2021
 
1953
2022
  if (get(record, 'isNew')) {
@@ -1977,6 +2046,9 @@ DS.Store = Ember.Object.extend(DS._Mappable, {
1977
2046
  */
1978
2047
  didSaveRecord: function(record, data) {
1979
2048
  if (data) {
2049
+ // normalize relationship IDs into records
2050
+ data = normalizeRelationships(this, record.constructor, data, record);
2051
+
1980
2052
  this.updateId(record, data);
1981
2053
  }
1982
2054
 
@@ -2069,7 +2141,7 @@ DS.Store = Ember.Object.extend(DS._Mappable, {
2069
2141
  @param {DS.Model} type
2070
2142
  @param {Object} data
2071
2143
  @param {Boolean} partial the data should be merged into
2072
- the existing fata, not replace it.
2144
+ the existing data, not replace it.
2073
2145
  */
2074
2146
  _load: function(type, data, partial) {
2075
2147
  var id = coerceId(data.id),
@@ -2086,20 +2158,23 @@ DS.Store = Ember.Object.extend(DS._Mappable, {
2086
2158
  methods that take a type key (like `find`, `createRecord`,
2087
2159
  etc.)
2088
2160
 
2089
- @param {String} key
2161
+ @method modelFor
2162
+ @param {String or subclass of DS.Model} key
2090
2163
  @returns {subclass of DS.Model}
2091
2164
  */
2092
2165
  modelFor: function(key) {
2093
- if (typeof key !== 'string') {
2094
- return key;
2095
- }
2166
+ var factory;
2096
2167
 
2097
- var factory = this.container.lookupFactory('model:'+key);
2168
+ if (typeof key === 'string') {
2169
+ factory = this.container.lookupFactory('model:' + key);
2098
2170
 
2171
+ factory.typeKey = key;
2172
+ } else {
2173
+ // A factory already supplied.
2174
+ factory = key;
2175
+ }
2099
2176
 
2100
2177
  factory.store = this;
2101
- factory.typeKey = key;
2102
-
2103
2178
  return factory;
2104
2179
  },
2105
2180
 
@@ -2169,7 +2244,7 @@ DS.Store = Ember.Object.extend(DS._Mappable, {
2169
2244
  // If passed, it means that the data should be
2170
2245
  // merged into the existing data, not replace it.
2171
2246
 
2172
- var serializer = this.serializerFor(type);
2247
+
2173
2248
  type = this.modelFor(type);
2174
2249
 
2175
2250
  // normalize relationship IDs into records
@@ -2180,7 +2255,47 @@ DS.Store = Ember.Object.extend(DS._Mappable, {
2180
2255
  return this.recordForId(type, data.id);
2181
2256
  },
2182
2257
 
2258
+ /**
2259
+ Push some raw data into the store.
2260
+
2261
+ The data will be automatically deserialized using the
2262
+ serializer for the `type` param.
2263
+
2264
+ This method can be used both to push in brand new
2265
+ records, as well as to update existing records.
2266
+
2267
+ You can push in more than one type of object at once.
2268
+ All objects should be in the format expected by the
2269
+ serializer.
2270
+
2271
+ ```js
2272
+ App.ApplicationSerializer = DS.ActiveModelSerializer;
2273
+
2274
+ var pushData = {
2275
+ posts: [
2276
+ {id: 1, post_title: "Great post", comment_ids: [2]}
2277
+ ],
2278
+ comments: [
2279
+ {id: 2, comment_body: "Insightful comment"}
2280
+ ]
2281
+ }
2282
+
2283
+ store.pushPayload('post', pushData);
2284
+ ```
2285
+
2286
+ @method push
2287
+ @param {String} type
2288
+ @param {Object} payload
2289
+ */
2290
+
2291
+ pushPayload: function (type, payload) {
2292
+ var serializer = this.serializerFor(type);
2293
+ serializer.pushPayload(this, payload);
2294
+ },
2295
+
2183
2296
  update: function(type, data) {
2297
+
2298
+
2184
2299
  return this.push(type, data, true);
2185
2300
  },
2186
2301
 
@@ -2230,9 +2345,12 @@ DS.Store = Ember.Object.extend(DS._Mappable, {
2230
2345
  idToRecord = typeMap.idToRecord;
2231
2346
 
2232
2347
 
2348
+ // lookupFactory should really return an object that creates
2349
+ // instances with the injections applied
2233
2350
  var record = type._create({
2234
2351
  id: id,
2235
2352
  store: this,
2353
+ container: this.container
2236
2354
  });
2237
2355
 
2238
2356
  if (data) {
@@ -2335,12 +2453,12 @@ DS.Store = Ember.Object.extend(DS._Mappable, {
2335
2453
  /**
2336
2454
  Returns the adapter for a given type.
2337
2455
 
2338
- @method adapterForType
2456
+ @method adapterFor
2339
2457
  @private
2340
2458
  @param {subclass of DS.Model} type
2341
2459
  @returns DS.Adapter
2342
2460
  */
2343
- adapterForType: function(type) {
2461
+ adapterFor: function(type) {
2344
2462
  var container = this.container, adapter;
2345
2463
 
2346
2464
  if (container) {
@@ -2372,29 +2490,31 @@ DS.Store = Ember.Object.extend(DS._Mappable, {
2372
2490
  */
2373
2491
  serializerFor: function(type) {
2374
2492
  type = this.modelFor(type);
2375
- var adapter = this.adapterForType(type);
2493
+ var adapter = this.adapterFor(type);
2376
2494
 
2377
2495
  return serializerFor(this.container, type.typeKey, adapter && adapter.defaultSerializer);
2378
2496
  }
2379
2497
  });
2380
2498
 
2381
- function normalizeRelationships(store, type, data) {
2499
+ function normalizeRelationships(store, type, data, record) {
2382
2500
  type.eachRelationship(function(key, relationship) {
2383
2501
  // A link (usually a URL) was already provided in
2384
2502
  // normalized form
2385
2503
  if (data.links && data.links[key]) {
2504
+ if (record && relationship.options.async) { record._relationships[key] = null; }
2386
2505
  return;
2387
2506
  }
2388
2507
 
2389
- var type = relationship.type,
2508
+ var kind = relationship.kind,
2390
2509
  value = data[key];
2391
2510
 
2392
2511
  if (value == null) { return; }
2393
2512
 
2394
- if (relationship.kind === 'belongsTo') {
2513
+ if (kind === 'belongsTo') {
2395
2514
  deserializeRecordId(store, data, key, relationship, value);
2396
- } else if (relationship.kind === 'hasMany') {
2515
+ } else if (kind === 'hasMany') {
2397
2516
  deserializeRecordIds(store, data, key, relationship, value);
2517
+ addUnsavedRecords(record, key, value);
2398
2518
  }
2399
2519
  });
2400
2520
 
@@ -2419,7 +2539,7 @@ function deserializeRecordId(store, data, key, relationship, id) {
2419
2539
 
2420
2540
  function typeFor(relationship, key, data) {
2421
2541
  if (relationship.options.polymorphic) {
2422
- return data[key + "_type"];
2542
+ return data[key + "Type"];
2423
2543
  } else {
2424
2544
  return relationship.type;
2425
2545
  }
@@ -2431,6 +2551,14 @@ function deserializeRecordIds(store, data, key, relationship, ids) {
2431
2551
  }
2432
2552
  }
2433
2553
 
2554
+ // If there are any unsaved records that are in a hasMany they won't be
2555
+ // in the payload, so add them back in manually.
2556
+ function addUnsavedRecords(record, key, data) {
2557
+ if(record) {
2558
+ data.pushObjects(record.get(key).filterBy('isNew'));
2559
+ }
2560
+ }
2561
+
2434
2562
  // Delegation to the adapter and promise management
2435
2563
 
2436
2564
  DS.PromiseArray = Ember.ArrayProxy.extend(Ember.PromiseProxyMixin);
@@ -2482,6 +2610,10 @@ function _find(adapter, store, type, id, resolver) {
2482
2610
  payload = serializer.extract(store, type, payload, id, 'find');
2483
2611
 
2484
2612
  return store.push(type, payload);
2613
+ }, function(error) {
2614
+ var record = store.getById(type, id);
2615
+ record.notFound();
2616
+ throw error;
2485
2617
  }).then(resolver.resolve, resolver.reject);
2486
2618
  }
2487
2619
 
@@ -2492,6 +2624,7 @@ function _findMany(adapter, store, type, ids, owner, resolver) {
2492
2624
  return resolve(promise).then(function(payload) {
2493
2625
  payload = serializer.extract(store, type, payload, null, 'findMany');
2494
2626
 
2627
+
2495
2628
  store.pushMany(type, payload);
2496
2629
  }).then(resolver.resolve, resolver.reject);
2497
2630
  }
@@ -2503,11 +2636,25 @@ function _findHasMany(adapter, store, record, link, relationship, resolver) {
2503
2636
  return resolve(promise).then(function(payload) {
2504
2637
  payload = serializer.extract(store, relationship.type, payload, null, 'findHasMany');
2505
2638
 
2639
+
2506
2640
  var records = store.pushMany(relationship.type, payload);
2507
2641
  record.updateHasMany(relationship.key, records);
2508
2642
  }).then(resolver.resolve, resolver.reject);
2509
2643
  }
2510
2644
 
2645
+ function _findBelongsTo(adapter, store, record, link, relationship, resolver) {
2646
+ var promise = adapter.findBelongsTo(store, record, link, relationship),
2647
+ serializer = serializerForAdapter(adapter, relationship.type);
2648
+
2649
+ return resolve(promise).then(function(payload) {
2650
+ payload = serializer.extract(store, relationship.type, payload, null, 'findBelongsTo');
2651
+
2652
+ var record = store.push(relationship.type, payload);
2653
+ record.updateBelongsTo(relationship.key, record);
2654
+ return record;
2655
+ }).then(resolver.resolve, resolver.reject);
2656
+ }
2657
+
2511
2658
  function _findAll(adapter, store, type, sinceToken, resolver) {
2512
2659
  var promise = adapter.findAll(store, type, sinceToken),
2513
2660
  serializer = serializerForAdapter(adapter, type);
@@ -2515,6 +2662,7 @@ function _findAll(adapter, store, type, sinceToken, resolver) {
2515
2662
  return resolve(promise).then(function(payload) {
2516
2663
  payload = serializer.extract(store, type, payload, null, 'findAll');
2517
2664
 
2665
+
2518
2666
  store.pushMany(type, payload);
2519
2667
  store.didUpdateAll(type);
2520
2668
  return store.all(type);
@@ -2528,6 +2676,7 @@ function _findQuery(adapter, store, type, query, recordArray, resolver) {
2528
2676
  return resolve(promise).then(function(payload) {
2529
2677
  payload = serializer.extract(store, type, payload, null, 'findAll');
2530
2678
 
2679
+
2531
2680
  recordArray.load(payload);
2532
2681
  return recordArray;
2533
2682
  }).then(resolver.resolve, resolver.reject);
@@ -2540,7 +2689,7 @@ function _commit(adapter, store, operation, record, resolver) {
2540
2689
 
2541
2690
 
2542
2691
  return promise.then(function(payload) {
2543
- payload = serializer.extract(store, type, payload, get(record, 'id'), operation);
2692
+ if (payload) { payload = serializer.extract(store, type, payload, get(record, 'id'), operation); }
2544
2693
  store.didSaveRecord(record, payload);
2545
2694
  return record;
2546
2695
  }, function(reason) {
@@ -2563,8 +2712,7 @@ function _commit(adapter, store, operation, record, resolver) {
2563
2712
  @module ember-data
2564
2713
  */
2565
2714
 
2566
- var get = Ember.get, set = Ember.set,
2567
- once = Ember.run.once, arrayMap = Ember.ArrayPolyfills.map;
2715
+ var get = Ember.get, set = Ember.set;
2568
2716
 
2569
2717
  /*
2570
2718
  WARNING: Much of these docs are inaccurate as of bf8497.
@@ -2732,10 +2880,14 @@ var hasDefinedProperties = function(object) {
2732
2880
  };
2733
2881
 
2734
2882
  var didSetProperty = function(record, context) {
2735
- if (context.value !== context.oldValue) {
2883
+ if (context.value === context.originalValue) {
2884
+ delete record._attributes[context.name];
2885
+ record.send('propertyWasReset', context.name);
2886
+ } else if (context.value !== context.oldValue) {
2736
2887
  record.send('becomeDirty');
2737
- record.updateRecordArraysLater();
2738
2888
  }
2889
+
2890
+ record.updateRecordArraysLater();
2739
2891
  };
2740
2892
 
2741
2893
  // Implementation notes:
@@ -2793,10 +2945,20 @@ var DirtyState = {
2793
2945
  // This means that there are local pending changes, but they
2794
2946
  // have not yet begun to be saved, and are not invalid.
2795
2947
  uncommitted: {
2796
-
2797
2948
  // EVENTS
2798
2949
  didSetProperty: didSetProperty,
2799
2950
 
2951
+ propertyWasReset: function(record, name) {
2952
+ var stillDirty = false;
2953
+
2954
+ for (var prop in record._attributes) {
2955
+ stillDirty = true;
2956
+ break;
2957
+ }
2958
+
2959
+ if (!stillDirty) { record.send('rolledBack'); }
2960
+ },
2961
+
2800
2962
  pushedData: Ember.K,
2801
2963
 
2802
2964
  becomeDirty: Ember.K,
@@ -2981,6 +3143,8 @@ var RootState = {
2981
3143
  // you out of the in-flight state.
2982
3144
  rolledBack: Ember.K,
2983
3145
 
3146
+ propertyWasReset: Ember.K,
3147
+
2984
3148
  // SUBSTATES
2985
3149
 
2986
3150
  // A record begins its lifecycle in the `empty` state.
@@ -2992,7 +3156,8 @@ var RootState = {
2992
3156
  isEmpty: true,
2993
3157
 
2994
3158
  // EVENTS
2995
- loadingData: function(record) {
3159
+ loadingData: function(record, promise) {
3160
+ record._loadingPromise = promise;
2996
3161
  record.transitionTo('loading');
2997
3162
  },
2998
3163
 
@@ -3006,6 +3171,7 @@ var RootState = {
3006
3171
 
3007
3172
  pushedData: function(record) {
3008
3173
  record.transitionTo('loaded.saved');
3174
+ record.triggerLater('didLoad');
3009
3175
  }
3010
3176
  },
3011
3177
 
@@ -3019,6 +3185,10 @@ var RootState = {
3019
3185
  // FLAGS
3020
3186
  isLoading: true,
3021
3187
 
3188
+ exit: function(record) {
3189
+ record._loadingPromise = null;
3190
+ },
3191
+
3022
3192
  // EVENTS
3023
3193
  pushedData: function(record) {
3024
3194
  record.transitionTo('loaded.saved');
@@ -3028,6 +3198,10 @@ var RootState = {
3028
3198
 
3029
3199
  becameError: function(record) {
3030
3200
  record.triggerLater('becameError', record);
3201
+ },
3202
+
3203
+ notFound: function(record) {
3204
+ record.transitionTo('empty');
3031
3205
  }
3032
3206
  },
3033
3207
 
@@ -3092,7 +3266,7 @@ var RootState = {
3092
3266
 
3093
3267
  didCommit: function(record) {
3094
3268
  record.send('invokeLifecycleCallbacks', get(record, 'lastDirtyType'));
3095
- },
3269
+ }
3096
3270
 
3097
3271
  },
3098
3272
 
@@ -3203,8 +3377,6 @@ var RootState = {
3203
3377
  }
3204
3378
  };
3205
3379
 
3206
- var hasOwnProp = {}.hasOwnProperty;
3207
-
3208
3380
  function wireState(object, parent, name) {
3209
3381
  /*jshint proto:true*/
3210
3382
  // TODO: Use Object.create and copy instead
@@ -3235,11 +3407,9 @@ DS.RootState = RootState;
3235
3407
  @module ember-data
3236
3408
  */
3237
3409
 
3238
- var get = Ember.get, set = Ember.set, map = Ember.EnumerableUtils.map,
3410
+ var get = Ember.get, set = Ember.set,
3239
3411
  merge = Ember.merge, once = Ember.run.once;
3240
3412
 
3241
- var arrayMap = Ember.ArrayPolyfills.map;
3242
-
3243
3413
  var retrieveFromCurrentState = Ember.computed(function(key, value) {
3244
3414
  return get(get(this, 'currentState'), key);
3245
3415
  }).property('currentState').readOnly();
@@ -3303,7 +3473,8 @@ DS.Model = Ember.Object.extend(Ember.Evented, {
3303
3473
  @returns {Object} A JSON representation of the object.
3304
3474
  */
3305
3475
  toJSON: function(options) {
3306
- var serializer = DS.JSONSerializer.create();
3476
+ // container is for lazy transform lookups
3477
+ var serializer = DS.JSONSerializer.create({ container: this.container });
3307
3478
  return serializer.serialize(this, options);
3308
3479
  },
3309
3480
 
@@ -3421,6 +3592,8 @@ DS.Model = Ember.Object.extend(Ember.Evented, {
3421
3592
  for (i=0, l=setups.length; i<l; i++) {
3422
3593
  setups[i].setup(this);
3423
3594
  }
3595
+
3596
+ this.updateRecordArraysLater();
3424
3597
  },
3425
3598
 
3426
3599
  _unhandledEvent: function(state, name, context) {
@@ -3440,22 +3613,45 @@ DS.Model = Ember.Object.extend(Ember.Evented, {
3440
3613
  if (transaction) { fn(transaction); }
3441
3614
  },
3442
3615
 
3443
- loadingData: function() {
3444
- this.send('loadingData');
3616
+ loadingData: function(promise) {
3617
+ this.send('loadingData', promise);
3445
3618
  },
3446
3619
 
3447
3620
  loadedData: function() {
3448
3621
  this.send('loadedData');
3449
3622
  },
3450
3623
 
3624
+ notFound: function() {
3625
+ this.send('notFound');
3626
+ },
3627
+
3451
3628
  pushedData: function() {
3452
3629
  this.send('pushedData');
3453
3630
  },
3454
3631
 
3632
+ /**
3633
+ Marks the record as deleted but does not save it. You must call
3634
+ `save` afterwards if you want to persist it. You might use this
3635
+ method if you want to allow the user to still `rollback()` a
3636
+ delete after it was made.
3637
+
3638
+ @method deleteRecord
3639
+ */
3455
3640
  deleteRecord: function() {
3456
3641
  this.send('deleteRecord');
3457
3642
  },
3458
3643
 
3644
+ /**
3645
+ Same as `deleteRecord`, but saves the record immediately.
3646
+
3647
+ @method destroyRecord
3648
+ @returns Promise
3649
+ */
3650
+ destroyRecord: function() {
3651
+ this.deleteRecord();
3652
+ return this.save();
3653
+ },
3654
+
3459
3655
  unloadRecord: function() {
3460
3656
 
3461
3657
 
@@ -3480,6 +3676,27 @@ DS.Model = Ember.Object.extend(Ember.Evented, {
3480
3676
  }
3481
3677
  },
3482
3678
 
3679
+ /**
3680
+ Gets the diff for the current model.
3681
+
3682
+ @method changedAttributes
3683
+
3684
+ @returns {Object} an object, whose keys are changed properties,
3685
+ and value is an [oldProp, newProp] array.
3686
+ */
3687
+ changedAttributes: function() {
3688
+ var oldData = get(this, '_data'),
3689
+ newData = get(this, '_attributes'),
3690
+ diffData = {},
3691
+ prop;
3692
+
3693
+ for (prop in newData) {
3694
+ diffData[prop] = [oldData[prop], newData[prop]];
3695
+ }
3696
+
3697
+ return diffData;
3698
+ },
3699
+
3483
3700
  adapterWillCommit: function() {
3484
3701
  this.send('willCommit');
3485
3702
  },
@@ -3525,6 +3742,7 @@ DS.Model = Ember.Object.extend(Ember.Evented, {
3525
3742
  var relationships = get(this.constructor, 'relationshipsByName');
3526
3743
  this.updateRecordArraysLater();
3527
3744
  relationships.forEach(function(name, relationship) {
3745
+ if (this._data.links && this._data.links[name]) { return; }
3528
3746
  if (relationship.kind === 'hasMany') {
3529
3747
  this.hasManyDidChange(relationship.key);
3530
3748
  }
@@ -3535,8 +3753,6 @@ DS.Model = Ember.Object.extend(Ember.Evented, {
3535
3753
  var hasMany = this._relationships[key];
3536
3754
 
3537
3755
  if (hasMany) {
3538
- var type = get(this.constructor, 'relationshipsByName').get(key).type;
3539
- var store = get(this, 'store');
3540
3756
  var records = this._data[key] || [];
3541
3757
 
3542
3758
  set(hasMany, 'content', Ember.A(records));
@@ -3559,6 +3775,7 @@ DS.Model = Ember.Object.extend(Ember.Evented, {
3559
3775
  var relationships = this._relationships;
3560
3776
 
3561
3777
  this.eachRelationship(function(name, rel) {
3778
+ if (data.links && data.links[name]) { return; }
3562
3779
  if (rel.options.async) { relationships[name] = null; }
3563
3780
  });
3564
3781
 
@@ -3587,8 +3804,18 @@ DS.Model = Ember.Object.extend(Ember.Evented, {
3587
3804
  this.hasManyDidChange(name);
3588
3805
  },
3589
3806
 
3807
+ updateBelongsTo: function(name, record) {
3808
+ this._data[name] = record;
3809
+ },
3810
+
3590
3811
  rollback: function() {
3591
3812
  this._attributes = {};
3813
+
3814
+ if (get(this, 'isError')) {
3815
+ this._inFlightAttributes = {};
3816
+ set(this, 'isError', false);
3817
+ }
3818
+
3592
3819
  this.send('rolledBack');
3593
3820
 
3594
3821
  this.suspendRelationshipObservers(function() {
@@ -3639,7 +3866,7 @@ DS.Model = Ember.Object.extend(Ember.Evented, {
3639
3866
  @method save
3640
3867
  */
3641
3868
  save: function() {
3642
- var resolver = Ember.RSVP.defer(), record = this;
3869
+ var resolver = Ember.RSVP.defer();
3643
3870
 
3644
3871
  this.get('store').scheduleSave(this, resolver);
3645
3872
  this._inFlightAttributes = this._attributes;
@@ -3871,12 +4098,11 @@ DS.attr = function(type, options) {
3871
4098
  options: options
3872
4099
  };
3873
4100
 
3874
- return Ember.computed(function(key, value, oldValue) {
3875
- var currentValue;
3876
-
4101
+ return Ember.computed(function(key, value) {
3877
4102
  if (arguments.length > 1) {
3878
4103
 
3879
- this.send('didSetProperty', { name: key, oldValue: this._attributes[key] || this._inFlightAttributes[key] || this._data[key], value: value });
4104
+ var oldValue = this._attributes[key] || this._inFlightAttributes[key] || this._data[key];
4105
+ this.send('didSetProperty', { name: key, oldValue: oldValue, originalValue: this._data[key], value: value });
3880
4106
  this._attributes[key] = value;
3881
4107
  return value;
3882
4108
  } else if (hasValue(this, key)) {
@@ -4429,18 +4655,23 @@ var get = Ember.get, set = Ember.set,
4429
4655
  function asyncBelongsTo(type, options, meta) {
4430
4656
  return Ember.computed(function(key, value) {
4431
4657
  var data = get(this, 'data'),
4432
- store = get(this, 'store'),
4433
- belongsTo;
4658
+ store = get(this, 'store');
4434
4659
 
4435
4660
  if (arguments.length === 2) {
4436
4661
 
4437
- return value === undefined ? null : value;
4662
+ return value === undefined ? null : DS.PromiseObject.create({ promise: Ember.RSVP.resolve(value) });
4438
4663
  }
4439
4664
 
4440
- belongsTo = data[key];
4665
+ var link = data.links && data.links[key],
4666
+ belongsTo = data[key];
4441
4667
 
4442
- if(!isNone(belongsTo) && get(belongsTo, 'isEmpty')) {
4443
- return store.fetchRecord(belongsTo);
4668
+ if(!isNone(belongsTo)) {
4669
+ var promise = store.fetchRecord(belongsTo) || Ember.RSVP.resolve(belongsTo);
4670
+ return DS.PromiseObject.create({promise: promise});
4671
+ } else if (link) {
4672
+ var resolver = Ember.RSVP.defer();
4673
+ store.findBelongsTo(this, link, meta, resolver);
4674
+ return DS.PromiseObject.create({ promise: resolver.promise });
4444
4675
  } else {
4445
4676
  return null;
4446
4677
  }
@@ -4448,7 +4679,12 @@ function asyncBelongsTo(type, options, meta) {
4448
4679
  }
4449
4680
 
4450
4681
  DS.belongsTo = function(type, options) {
4682
+ if (typeof type === 'object') {
4683
+ options = type;
4684
+ type = undefined;
4685
+ } else {
4451
4686
 
4687
+ }
4452
4688
 
4453
4689
  options = options || {};
4454
4690
 
@@ -4463,11 +4699,7 @@ DS.belongsTo = function(type, options) {
4463
4699
  store = get(this, 'store'), belongsTo, typeClass;
4464
4700
 
4465
4701
  if (typeof type === 'string') {
4466
- if (type.indexOf(".") === -1) {
4467
- typeClass = store.modelFor(type);
4468
- } else {
4469
- typeClass = get(Ember.lookup, type);
4470
- }
4702
+ typeClass = store.modelFor(type);
4471
4703
  } else {
4472
4704
  typeClass = type;
4473
4705
  }
@@ -4481,9 +4713,7 @@ DS.belongsTo = function(type, options) {
4481
4713
 
4482
4714
  if (isNone(belongsTo)) { return null; }
4483
4715
 
4484
- if (get(belongsTo, 'isEmpty')) {
4485
- store.fetchRecord(belongsTo);
4486
- }
4716
+ store.fetchRecord(belongsTo);
4487
4717
 
4488
4718
  return belongsTo;
4489
4719
  }).property('data').meta(meta);
@@ -4507,11 +4737,12 @@ DS.Model.reopen({
4507
4737
  */
4508
4738
  belongsToWillChange: Ember.beforeObserver(function(record, key) {
4509
4739
  if (get(record, 'isLoaded')) {
4510
- var oldParent = get(record, key),
4511
- store = get(record, 'store');
4740
+ var oldParent = get(record, key);
4741
+
4742
+ if (oldParent) {
4743
+ var store = get(record, 'store'),
4744
+ change = DS.RelationshipChange.createChange(record, oldParent, store, { key: key, kind: "belongsTo", changeType: "remove" });
4512
4745
 
4513
- if (oldParent){
4514
- var change = DS.RelationshipChange.createChange(record, oldParent, store, { key: key, kind: "belongsTo", changeType: "remove" });
4515
4746
  change.sync();
4516
4747
  this._changesToSync[key] = change;
4517
4748
  }
@@ -4528,7 +4759,8 @@ DS.Model.reopen({
4528
4759
  belongsToDidChange: Ember.immediateObserver(function(record, key) {
4529
4760
  if (get(record, 'isLoaded')) {
4530
4761
  var newParent = get(record, key);
4531
- if(newParent){
4762
+
4763
+ if (newParent) {
4532
4764
  var store = get(record, 'store'),
4533
4765
  change = DS.RelationshipChange.createChange(record, newParent, store, { key: key, kind: "belongsTo", changeType: "add" });
4534
4766
 
@@ -4550,10 +4782,11 @@ DS.Model.reopen({
4550
4782
  */
4551
4783
 
4552
4784
  var get = Ember.get, set = Ember.set, setProperties = Ember.setProperties;
4553
- var forEach = Ember.EnumerableUtils.forEach;
4554
4785
 
4555
4786
  function asyncHasMany(type, options, meta) {
4556
4787
  return Ember.computed(function(key, value) {
4788
+ if (this._relationships[key]) { return this._relationships[key]; }
4789
+
4557
4790
  var resolver = Ember.RSVP.defer();
4558
4791
 
4559
4792
  var relationship = buildRelationship(this, key, options, function(store, data) {
@@ -4608,7 +4841,10 @@ function hasRelationship(type, options) {
4608
4841
  }
4609
4842
 
4610
4843
  DS.hasMany = function(type, options) {
4611
-
4844
+ if (typeof type === 'object') {
4845
+ options = type;
4846
+ type = undefined;
4847
+ }
4612
4848
  return hasRelationship(type, options);
4613
4849
  };
4614
4850
 
@@ -4647,7 +4883,7 @@ DS.Model.reopen({
4647
4883
  being defined. So, for example, when the user does this:
4648
4884
 
4649
4885
  DS.Model.extend({
4650
- parent: DS.belongsTo(App.User)
4886
+ parent: DS.belongsTo('user')
4651
4887
  });
4652
4888
 
4653
4889
  This hook would be called with "parent" as the key and the computed
@@ -4701,7 +4937,7 @@ DS.Model.reopenClass({
4701
4937
  For example, if you define a model like this:
4702
4938
 
4703
4939
  App.Post = DS.Model.extend({
4704
- comments: DS.hasMany(App.Comment)
4940
+ comments: DS.hasMany('comment')
4705
4941
  });
4706
4942
 
4707
4943
  Calling `App.Post.typeForRelationship('comments')` will return `App.Comment`.
@@ -4774,9 +5010,9 @@ DS.Model.reopenClass({
4774
5010
  For example, given the following model definition:
4775
5011
 
4776
5012
  App.Blog = DS.Model.extend({
4777
- users: DS.hasMany(App.User),
4778
- owner: DS.belongsTo(App.User),
4779
- posts: DS.hasMany(App.Post)
5013
+ users: DS.hasMany('user'),
5014
+ owner: DS.belongsTo('user'),
5015
+ posts: DS.hasMany('post')
4780
5016
  });
4781
5017
 
4782
5018
  This computed property would return a map describing these
@@ -4806,7 +5042,7 @@ DS.Model.reopenClass({
4806
5042
  // it to the map.
4807
5043
  if (meta.isRelationship) {
4808
5044
  if (typeof meta.type === 'string') {
4809
- meta.type = Ember.get(Ember.lookup, meta.type);
5045
+ meta.type = this.store.modelFor(meta.type);
4810
5046
  }
4811
5047
 
4812
5048
  var relationshipsForType = map.get(meta.type);
@@ -4824,10 +5060,10 @@ DS.Model.reopenClass({
4824
5060
  definition:
4825
5061
 
4826
5062
  App.Blog = DS.Model.extend({
4827
- users: DS.hasMany(App.User),
4828
- owner: DS.belongsTo(App.User),
5063
+ users: DS.hasMany('user'),
5064
+ owner: DS.belongsTo('user'),
4829
5065
 
4830
- posts: DS.hasMany(App.Post)
5066
+ posts: DS.hasMany('post')
4831
5067
  });
4832
5068
 
4833
5069
  This property would contain the following:
@@ -4863,9 +5099,10 @@ DS.Model.reopenClass({
4863
5099
  For example, given a model with this definition:
4864
5100
 
4865
5101
  App.Blog = DS.Model.extend({
4866
- users: DS.hasMany(App.User),
4867
- owner: DS.belongsTo(App.User),
4868
- posts: DS.hasMany(App.Post)
5102
+ users: DS.hasMany('user'),
5103
+ owner: DS.belongsTo('user'),
5104
+
5105
+ posts: DS.hasMany('post')
4869
5106
  });
4870
5107
 
4871
5108
  This property would contain the following:
@@ -4890,7 +5127,7 @@ DS.Model.reopenClass({
4890
5127
  type = meta.type;
4891
5128
 
4892
5129
  if (typeof type === 'string') {
4893
- type = get(this, type, false) || get(Ember.lookup, type);
5130
+ type = get(this, type, false) || this.store.modelFor(type);
4894
5131
  }
4895
5132
 
4896
5133
 
@@ -4912,10 +5149,10 @@ DS.Model.reopenClass({
4912
5149
  definition:
4913
5150
 
4914
5151
  App.Blog = DS.Model.extend({
4915
- users: DS.hasMany(App.User),
4916
- owner: DS.belongsTo(App.User),
5152
+ users: DS.hasMany('user'),
5153
+ owner: DS.belongsTo('user'),
4917
5154
 
4918
- posts: DS.hasMany(App.Post)
5155
+ posts: DS.hasMany('post')
4919
5156
  });
4920
5157
 
4921
5158
  This property would contain the following:
@@ -4939,6 +5176,12 @@ DS.Model.reopenClass({
4939
5176
  meta.key = name;
4940
5177
  type = meta.type;
4941
5178
 
5179
+ if (!type && meta.kind === 'hasMany') {
5180
+ type = Ember.String.singularize(name);
5181
+ } else if (!type) {
5182
+ type = name;
5183
+ }
5184
+
4942
5185
  if (typeof type === 'string') {
4943
5186
  meta.type = this.store.modelFor(type);
4944
5187
  }
@@ -4958,10 +5201,10 @@ DS.Model.reopenClass({
4958
5201
  For example:
4959
5202
 
4960
5203
  App.Blog = DS.Model.extend({
4961
- users: DS.hasMany(App.User),
4962
- owner: DS.belongsTo(App.User),
5204
+ users: DS.hasMany('user'),
5205
+ owner: DS.belongsTo('user'),
4963
5206
 
4964
- posts: DS.hasMany(App.Post),
5207
+ posts: DS.hasMany('post'),
4965
5208
 
4966
5209
  title: DS.attr('string')
4967
5210
  });
@@ -5267,9 +5510,8 @@ DS.RecordArrayManager = Ember.Object.extend({
5267
5510
  @module ember-data
5268
5511
  */
5269
5512
 
5270
- var get = Ember.get, set = Ember.set, merge = Ember.merge;
5513
+ var get = Ember.get, set = Ember.set;
5271
5514
  var map = Ember.ArrayPolyfills.map;
5272
- var resolve = Ember.RSVP.resolve;
5273
5515
 
5274
5516
  var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack'];
5275
5517
 
@@ -5283,18 +5525,6 @@ DS.InvalidError = function(errors) {
5283
5525
  };
5284
5526
  DS.InvalidError.prototype = Ember.create(Error.prototype);
5285
5527
 
5286
- function isThenable(object) {
5287
- return object && typeof object.then === 'function';
5288
- }
5289
-
5290
- // Simple dispatcher to support overriding the aliased
5291
- // method in subclasses.
5292
- function aliasMethod(methodName) {
5293
- return function() {
5294
- return this[methodName].apply(this, arguments);
5295
- };
5296
- }
5297
-
5298
5528
  /**
5299
5529
  An adapter is an object that receives requests from a store and
5300
5530
  translates them into the appropriate action to take against your
@@ -5348,8 +5578,8 @@ DS.Adapter = Ember.Object.extend(DS._Mappable, {
5348
5578
  The `find()` method is invoked when the store is asked for a record that
5349
5579
  has not previously been loaded. In response to `find()` being called, you
5350
5580
  should query your persistence layer for a record with the given ID. Once
5351
- found, you can asynchronously call the store's `load()` method to load
5352
- the record.
5581
+ found, you can asynchronously call the store's `push()` method to push
5582
+ the record into the store.
5353
5583
 
5354
5584
  Here is an example `find` implementation:
5355
5585
 
@@ -5360,8 +5590,8 @@ DS.Adapter = Ember.Object.extend(DS._Mappable, {
5360
5590
  jQuery.getJSON(url, function(data) {
5361
5591
  // data is a hash of key/value pairs. If your server returns a
5362
5592
  // root, simply do something like:
5363
- // store.load(type, id, data.person)
5364
- store.load(type, id, data);
5593
+ // store.push(type, id, data.person)
5594
+ store.push(type, id, data);
5365
5595
  });
5366
5596
  }
5367
5597
 
@@ -5436,9 +5666,9 @@ DS.Adapter = Ember.Object.extend(DS._Mappable, {
5436
5666
  method on success or `didError` method on failure.
5437
5667
 
5438
5668
  @method createRecord
5439
- @property {DS.Store} store
5440
- @property {subclass of DS.Model} type the DS.Model class of the record
5441
- @property {DS.Model} record
5669
+ @param {DS.Store} store
5670
+ @param {subclass of DS.Model} type the DS.Model class of the record
5671
+ @param {DS.Model} record
5442
5672
  */
5443
5673
  createRecord: Ember.required(Function),
5444
5674
 
@@ -5449,9 +5679,9 @@ DS.Adapter = Ember.Object.extend(DS._Mappable, {
5449
5679
  Serializes the record update and send it to the server.
5450
5680
 
5451
5681
  @method updateRecord
5452
- @property {DS.Store} store
5453
- @property {subclass of DS.Model} type the DS.Model class of the record
5454
- @property {DS.Model} record
5682
+ @param {DS.Store} store
5683
+ @param {subclass of DS.Model} type the DS.Model class of the record
5684
+ @param {DS.Model} record
5455
5685
  */
5456
5686
  updateRecord: Ember.required(Function),
5457
5687
 
@@ -5462,9 +5692,9 @@ DS.Adapter = Ember.Object.extend(DS._Mappable, {
5462
5692
  Sends a delete request for the record to the server.
5463
5693
 
5464
5694
  @method deleteRecord
5465
- @property {DS.Store} store
5466
- @property {subclass of DS.Model} type the DS.Model class of the record
5467
- @property {DS.Model} record
5695
+ @param {DS.Store} store
5696
+ @param {subclass of DS.Model} type the DS.Model class of the record
5697
+ @param {DS.Model} record
5468
5698
  */
5469
5699
  deleteRecord: Ember.required(Function),
5470
5700
 
@@ -5476,9 +5706,9 @@ DS.Adapter = Ember.Object.extend(DS._Mappable, {
5476
5706
  server requests.
5477
5707
 
5478
5708
  @method findMany
5479
- @property {DS.Store} store
5480
- @property {subclass of DS.Model} type the DS.Model class of the records
5481
- @property {Array} ids
5709
+ @param {DS.Store} store
5710
+ @param {subclass of DS.Model} type the DS.Model class of the records
5711
+ @param {Array} ids
5482
5712
  */
5483
5713
  findMany: function(store, type, ids) {
5484
5714
  var promises = map.call(ids, function(id) {
@@ -5575,7 +5805,7 @@ DS.FixtureAdapter = DS.Adapter.extend({
5575
5805
  },
5576
5806
 
5577
5807
  /**
5578
- Implement this method in order to provide provide json for CRUD methods
5808
+ Implement this method in order to provide json for CRUD methods
5579
5809
 
5580
5810
  @method mockJSON
5581
5811
  @param type
@@ -5591,7 +5821,7 @@ DS.FixtureAdapter = DS.Adapter.extend({
5591
5821
  @param record
5592
5822
  */
5593
5823
  generateIdForRecord: function(store) {
5594
- return counter++;
5824
+ return "fixture-" + counter++;
5595
5825
  },
5596
5826
 
5597
5827
  /**
@@ -5803,6 +6033,7 @@ DS.FixtureAdapter = DS.Adapter.extend({
5803
6033
 
5804
6034
  var get = Ember.get, set = Ember.set;
5805
6035
  var forEach = Ember.ArrayPolyfills.forEach;
6036
+ var map = Ember.ArrayPolyfills.map;
5806
6037
 
5807
6038
  function coerceId(id) {
5808
6039
  return id == null ? null : id+'';
@@ -5843,6 +6074,10 @@ function coerceId(id) {
5843
6074
  You can also implement `keyForRelationship`, which takes the name
5844
6075
  of the relationship as the first parameter, and the kind of
5845
6076
  relationship (`hasMany` or `belongsTo`) as the second parameter.
6077
+
6078
+ @class RESTSerializer
6079
+ @namespace DS
6080
+ @extends DS.JSONSerializer
5846
6081
  */
5847
6082
  DS.RESTSerializer = DS.JSONSerializer.extend({
5848
6083
  /**
@@ -5922,6 +6157,31 @@ DS.RESTSerializer = DS.JSONSerializer.extend({
5922
6157
  return this._super(type, hash, prop);
5923
6158
  },
5924
6159
 
6160
+ /**
6161
+ You can use this method to normalize all payloads, regardless of whether they
6162
+ represent single records or an array.
6163
+
6164
+ For example, you might want to remove some extraneous data from the payload:
6165
+
6166
+ ```js
6167
+ App.ApplicationSerializer = DS.RESTSerializer.extend({
6168
+ normalizePayload: function(type, payload) {
6169
+ delete payload.version;
6170
+ delete payload.status;
6171
+ return payload;
6172
+ }
6173
+ });
6174
+ ```
6175
+
6176
+ @method normalizePayload
6177
+ @param {subclass of DS.Model} type
6178
+ @param {Object} hash
6179
+ @returns Object the normalized payload
6180
+ */
6181
+ normalizePayload: function(type, payload) {
6182
+ return payload;
6183
+ },
6184
+
5925
6185
  /**
5926
6186
  @method normalizeId
5927
6187
  @private
@@ -6057,6 +6317,7 @@ DS.RESTSerializer = DS.JSONSerializer.extend({
6057
6317
  for the first time or updated (`createRecord` or `updateRecord`). In
6058
6318
  particular, it will update the properties of the record that was saved.
6059
6319
 
6320
+ @method extractSingle
6060
6321
  @param {DS.Store} store
6061
6322
  @param {subclass of DS.Model} type
6062
6323
  @param {Object} payload
@@ -6065,25 +6326,33 @@ DS.RESTSerializer = DS.JSONSerializer.extend({
6065
6326
  @returns Object the primary response to the original request
6066
6327
  */
6067
6328
  extractSingle: function(store, primaryType, payload, recordId, requestType) {
6329
+ payload = this.normalizePayload(primaryType, payload);
6330
+
6068
6331
  var primaryTypeName = primaryType.typeKey,
6069
6332
  primaryRecord;
6070
6333
 
6071
6334
  for (var prop in payload) {
6072
- // legacy support for singular names
6073
- if (prop === primaryTypeName) {
6335
+ var typeName = this.typeForRoot(prop),
6336
+ isPrimary = typeName === primaryTypeName;
6337
+
6338
+ // legacy support for singular resources
6339
+ if (isPrimary && Ember.typeOf(payload[prop]) !== "array" ) {
6074
6340
  primaryRecord = this.normalize(primaryType, payload[prop], prop);
6075
6341
  continue;
6076
6342
  }
6077
6343
 
6078
- var typeName = this.singularize(prop),
6079
- type = store.modelFor(typeName);
6344
+ var type = store.modelFor(typeName);
6080
6345
 
6081
6346
  /*jshint loopfunc:true*/
6082
6347
  forEach.call(payload[prop], function(hash) {
6083
- hash = this.normalize(type, hash, prop);
6348
+ var typeName = this.typeForRoot(prop),
6349
+ type = store.modelFor(typeName),
6350
+ typeSerializer = store.serializerFor(type);
6084
6351
 
6085
- var isFirstCreatedRecord = typeName === primaryTypeName && !recordId && !primaryRecord,
6086
- isUpdatedRecord = typeName === primaryTypeName && coerceId(hash.id) === recordId;
6352
+ hash = typeSerializer.normalize(type, hash, prop);
6353
+
6354
+ var isFirstCreatedRecord = isPrimary && !recordId && !primaryRecord,
6355
+ isUpdatedRecord = isPrimary && coerceId(hash.id) === recordId;
6087
6356
 
6088
6357
  // find the primary record.
6089
6358
  //
@@ -6190,6 +6459,12 @@ DS.RESTSerializer = DS.JSONSerializer.extend({
6190
6459
  or `findHasMany`. In particular, the primary array will become the
6191
6460
  list of records in the record array that kicked off the request.
6192
6461
 
6462
+ If your primary array contains secondary (embedded) records of the same type,
6463
+ you cannot place these into the primary array `posts`. Instead, place the
6464
+ secondary items into an underscore prefixed property `_posts`, which will
6465
+ push these items into the store and will not affect the resulting query.
6466
+
6467
+ @method extractArray
6193
6468
  @param {DS.Store} store
6194
6469
  @param {subclass of DS.Model} type
6195
6470
  @param {Object} payload
@@ -6198,17 +6473,28 @@ DS.RESTSerializer = DS.JSONSerializer.extend({
6198
6473
  to the original query.
6199
6474
  */
6200
6475
  extractArray: function(store, primaryType, payload) {
6476
+ payload = this.normalizePayload(primaryType, payload);
6477
+
6201
6478
  var primaryTypeName = primaryType.typeKey,
6202
6479
  primaryArray;
6203
6480
 
6204
6481
  for (var prop in payload) {
6205
- var typeName = this.singularize(prop),
6482
+ var typeKey = prop,
6483
+ forcedSecondary = false;
6484
+
6485
+ if (prop.charAt(0) === '_') {
6486
+ forcedSecondary = true;
6487
+ typeKey = prop.substr(1);
6488
+ }
6489
+
6490
+ var typeName = this.typeForRoot(typeKey),
6206
6491
  type = store.modelFor(typeName),
6207
- isPrimary = typeName === primaryTypeName;
6492
+ typeSerializer = store.serializerFor(type),
6493
+ isPrimary = (!forcedSecondary && (typeName === primaryTypeName));
6208
6494
 
6209
6495
  /*jshint loopfunc:true*/
6210
- var normalizedArray = payload[prop].map(function(hash) {
6211
- return this.normalize(type, hash, prop);
6496
+ var normalizedArray = map.call(payload[prop], function(hash) {
6497
+ return typeSerializer.normalize(type, hash, prop);
6212
6498
  }, this);
6213
6499
 
6214
6500
  if (isPrimary) {
@@ -6222,28 +6508,81 @@ DS.RESTSerializer = DS.JSONSerializer.extend({
6222
6508
  },
6223
6509
 
6224
6510
  /**
6225
- @private
6226
- @method pluralize
6227
- @param {String} key
6228
- */
6229
- pluralize: function(key) {
6230
- return Ember.String.pluralize(key);
6231
- },
6511
+ This method allows you to push a payload containing top-level
6512
+ collections of records organized per type.
6232
6513
 
6233
- /**
6234
- @private
6235
- @method singularize
6236
- @param {String} key
6237
- */
6238
- singularize: function(key) {
6239
- return Ember.String.singularize(key);
6240
- },
6514
+ ```js
6515
+ {
6516
+ "posts": [{
6517
+ "id": "1",
6518
+ "title": "Rails is omakase",
6519
+ "author", "1",
6520
+ "comments": [ "1" ]
6521
+ }],
6522
+ "comments": [{
6523
+ "id": "1",
6524
+ "body": "FIRST
6525
+ }],
6526
+ "users": [{
6527
+ "id": "1",
6528
+ "name": "@d2h"
6529
+ }]
6530
+ }
6531
+ ```
6241
6532
 
6242
- // SERIALIZE
6533
+ It will first normalize the payload, so you can use this to push
6534
+ in data streaming in from your server structured the same way
6535
+ that fetches and saves are structured.
6243
6536
 
6244
- /**
6245
- Called when a record is saved in order to convert the
6246
- record into JSON.
6537
+ @method pushPayload
6538
+ @param {DS.Store} store
6539
+ @param {Object} payload
6540
+ */
6541
+ pushPayload: function(store, payload) {
6542
+ payload = this.normalizePayload(null, payload);
6543
+
6544
+ for (var prop in payload) {
6545
+ var typeName = this.typeForRoot(prop),
6546
+ type = store.modelFor(typeName);
6547
+
6548
+ /*jshint loopfunc:true*/
6549
+ var normalizedArray = map.call(payload[prop], function(hash) {
6550
+ return this.normalize(type, hash, prop);
6551
+ }, this);
6552
+
6553
+ store.pushMany(typeName, normalizedArray);
6554
+ }
6555
+ },
6556
+
6557
+ /**
6558
+ You can use this method to normalize the JSON root keys returned
6559
+ into the model type expected by your store.
6560
+
6561
+ For example, your server may return underscored root keys rather than
6562
+ the expected camelcased versions.
6563
+
6564
+ ```js
6565
+ App.ApplicationSerializer = DS.RESTSerializer.extend({
6566
+ typeForRoot: function(root) {
6567
+ var camelized = Ember.String.camelize(root);
6568
+ return Ember.String.singularize(camelized);
6569
+ }
6570
+ });
6571
+ ```
6572
+
6573
+ @method typeForRoot
6574
+ @param {String} root
6575
+ @returns String the model's typeKey
6576
+ */
6577
+ typeForRoot: function(root) {
6578
+ return Ember.String.singularize(root);
6579
+ },
6580
+
6581
+ // SERIALIZE
6582
+
6583
+ /**
6584
+ Called when a record is saved in order to convert the
6585
+ record into JSON.
6247
6586
 
6248
6587
  By default, it creates a JSON object with a key for
6249
6588
  each attribute and belongsTo relationship.
@@ -6378,9 +6717,54 @@ DS.RESTSerializer = DS.JSONSerializer.extend({
6378
6717
  }
6379
6718
  });
6380
6719
  ```
6720
+
6721
+ @method serialize
6722
+ @param record
6723
+ @param options
6381
6724
  */
6382
6725
  serialize: function(record, options) {
6383
6726
  return this._super.apply(this, arguments);
6727
+ },
6728
+
6729
+ /**
6730
+ You can use this method to customize the root keys serialized into the JSON.
6731
+ By default the REST Serializer sends camelized root keys.
6732
+ For example, your server may expect underscored root objects.
6733
+
6734
+ ```js
6735
+ App.ApplicationSerializer = DS.RESTSerializer.extend({
6736
+ serializeIntoHash: function(data, type, record, options) {
6737
+ var root = Ember.String.decamelize(type.typeKey);
6738
+ data[root] = this.serialize(record, options);
6739
+ }
6740
+ });
6741
+ ```
6742
+
6743
+ @method serializeIntoHash
6744
+ @param {Object} hash
6745
+ @param {subclass of DS.Model} type
6746
+ @param {DS.Model} record
6747
+ @param {Object} options
6748
+ */
6749
+ serializeIntoHash: function(hash, type, record, options) {
6750
+ hash[type.typeKey] = this.serialize(record, options);
6751
+ },
6752
+
6753
+ /**
6754
+ You can use this method to customize how polymorphic objects are serialized.
6755
+ By default the JSON Serializer creates the key by appending `Type` to
6756
+ the attribute and value from the model's camelcased model name.
6757
+
6758
+ @method serializePolymorphicType
6759
+ @param {DS.Model} record
6760
+ @param {Object} json
6761
+ @param relationship
6762
+ */
6763
+ serializePolymorphicType: function(record, json, relationship) {
6764
+ var key = relationship.key,
6765
+ belongsTo = get(record, key);
6766
+ key = this.keyForAttribute ? this.keyForAttribute(key) : key;
6767
+ json[key + "Type"] = belongsTo.constructor.typeKey;
6384
6768
  }
6385
6769
  });
6386
6770
 
@@ -6426,7 +6810,7 @@ var forEach = Ember.ArrayPolyfills.forEach;
6426
6810
 
6427
6811
  ### Conventional Names
6428
6812
 
6429
- Attribute names in your JSON payload should be the underscored versions of
6813
+ Attribute names in your JSON payload should be the camelcased versions of
6430
6814
  the attributes in your Ember.js models.
6431
6815
 
6432
6816
  For example, if you have a `Person` model:
@@ -6444,8 +6828,8 @@ var forEach = Ember.ArrayPolyfills.forEach;
6444
6828
  ```js
6445
6829
  {
6446
6830
  "person": {
6447
- "first_name": "Barack",
6448
- "last_name": "Obama",
6831
+ "firstName": "Barack",
6832
+ "lastName": "Obama",
6449
6833
  "occupation": "President"
6450
6834
  }
6451
6835
  }
@@ -6623,6 +7007,8 @@ DS.RESTAdapter = DS.Adapter.extend({
6623
7007
  This method will be called with the parent record and `/posts/1/comments`.
6624
7008
 
6625
7009
  It will make an Ajax request to the originally specified URL.
7010
+ If the URL is host-relative (starting with a single slash), the
7011
+ request will use the host specified on the adapter (if any).
6626
7012
 
6627
7013
  @method findHasMany
6628
7014
  @see RESTAdapter/buildURL
@@ -6633,7 +7019,51 @@ DS.RESTAdapter = DS.Adapter.extend({
6633
7019
  @returns Promise
6634
7020
  */
6635
7021
  findHasMany: function(store, record, url) {
6636
- return this.ajax(url, 'GET');
7022
+ var host = get(this, 'host'),
7023
+ id = get(record, 'id'),
7024
+ type = record.constructor.typeKey;
7025
+
7026
+ if (host && url.charAt(0) === '/' && url.charAt(1) !== '/') {
7027
+ url = host + url;
7028
+ }
7029
+
7030
+ return this.ajax(this.urlPrefix(url, this.buildURL(type, id)), 'GET');
7031
+ },
7032
+
7033
+ /**
7034
+ Called by the store in order to fetch a JSON array for
7035
+ the unloaded records in a belongs-to relationship that were originally
7036
+ specified as a URL (inside of `links`).
7037
+
7038
+ For example, if your original payload looks like this:
7039
+
7040
+ ```js
7041
+ {
7042
+ "person": {
7043
+ "id": 1,
7044
+ "name": "Tom Dale",
7045
+ "links": { "group": "/people/1/group" }
7046
+ }
7047
+ }
7048
+ ```
7049
+
7050
+ This method will be called with the parent record and `/people/1/group`.
7051
+
7052
+ It will make an Ajax request to the originally specified URL.
7053
+
7054
+ @method findBelongsTo
7055
+ @see RESTAdapter/buildURL
7056
+ @see RESTAdapter/ajax
7057
+ @param {DS.Store} store
7058
+ @param {DS.Model} record
7059
+ @param {String} url
7060
+ @returns Promise
7061
+ */
7062
+ findBelongsTo: function(store, record, url) {
7063
+ var id = get(record, 'id'),
7064
+ type = record.constructor.typeKey;
7065
+
7066
+ return this.ajax(this.urlPrefix(url, this.buildURL(type, id)), 'GET');
6637
7067
  },
6638
7068
 
6639
7069
  /**
@@ -6656,7 +7086,9 @@ DS.RESTAdapter = DS.Adapter.extend({
6656
7086
  */
6657
7087
  createRecord: function(store, type, record) {
6658
7088
  var data = {};
6659
- data[type.typeKey] = store.serializerFor(type.typeKey).serialize(record, { includeId: true });
7089
+ var serializer = store.serializerFor(type.typeKey);
7090
+
7091
+ serializer.serializeIntoHash(data, type, record, { includeId: true });
6660
7092
 
6661
7093
  return this.ajax(this.buildURL(type.typeKey), "POST", { data: data });
6662
7094
  },
@@ -6680,7 +7112,9 @@ DS.RESTAdapter = DS.Adapter.extend({
6680
7112
  */
6681
7113
  updateRecord: function(store, type, record) {
6682
7114
  var data = {};
6683
- data[type.typeKey] = store.serializerFor(type.typeKey).serialize(record);
7115
+ var serializer = store.serializerFor(type.typeKey);
7116
+
7117
+ serializer.serializeIntoHash(data, type, record);
6684
7118
 
6685
7119
  var id = get(record, 'id');
6686
7120
 
@@ -6710,7 +7144,10 @@ DS.RESTAdapter = DS.Adapter.extend({
6710
7144
  /**
6711
7145
  Builds a URL for a given type and optional ID.
6712
7146
 
6713
- If an ID is specified, it adds the ID to the root generated
7147
+ By default, it pluralizes the type's name (for example,
7148
+ 'post' becomes 'posts' and 'person' becomes 'people').
7149
+
7150
+ If an ID is specified, it adds the ID to the path generated
6714
7151
  for the type, separated by a `/`.
6715
7152
 
6716
7153
  @method buildURL
@@ -6719,50 +7156,95 @@ DS.RESTAdapter = DS.Adapter.extend({
6719
7156
  @returns String
6720
7157
  */
6721
7158
  buildURL: function(type, id) {
6722
- var host = get(this, 'host'),
6723
- namespace = get(this, 'namespace'),
6724
- url = [];
6725
-
6726
- if (host) { url.push(host); }
6727
- if (namespace) { url.push(namespace); }
7159
+ var url = [],
7160
+ host = get(this, 'host'),
7161
+ prefix = this.urlPrefix();
6728
7162
 
6729
- url.push(this.rootForType(type));
7163
+ if (type) { url.push(this.pathForType(type)); }
6730
7164
  if (id) { url.push(id); }
6731
7165
 
7166
+ if (prefix) { url.unshift(prefix); }
7167
+
6732
7168
  url = url.join('/');
6733
- if (!host) { url = '/' + url; }
7169
+ if (!host && url) { url = '/' + url; }
6734
7170
 
6735
7171
  return url;
6736
7172
  },
6737
7173
 
7174
+ urlPrefix: function(path, parentURL) {
7175
+ var host = get(this, 'host'),
7176
+ namespace = get(this, 'namespace'),
7177
+ url = [];
7178
+
7179
+ if (path) {
7180
+ // Absolute path
7181
+ if (path.charAt(0) === '/') {
7182
+ if (host) {
7183
+ path = path.slice(1);
7184
+ url.push(host);
7185
+ }
7186
+ // Relative path
7187
+ } else if (!/^http(s)?:\/\//.test(path)) {
7188
+ url.push(parentURL);
7189
+ }
7190
+ } else {
7191
+ if (host) { url.push(host); }
7192
+ if (namespace) { url.push(namespace); }
7193
+ }
7194
+
7195
+ if (path) {
7196
+ url.push(path);
7197
+ }
7198
+
7199
+ return url.join('/');
7200
+ },
7201
+
6738
7202
  /**
6739
- Determines the pathname root for a given type.
7203
+ Determines the pathname for a given type.
6740
7204
 
6741
7205
  By default, it pluralizes the type's name (for example,
6742
7206
  'post' becomes 'posts' and 'person' becomes 'people').
6743
7207
 
6744
- ### Pathname root customization
7208
+ ### Pathname customization
6745
7209
 
6746
7210
  For example if you have an object LineItem with an
6747
7211
  endpoint of "/line_items/".
6748
7212
 
6749
7213
  ```js
6750
7214
  DS.RESTAdapter.reopen({
6751
- rootForType: function(type) {
7215
+ pathForType: function(type) {
6752
7216
  var decamelized = Ember.String.decamelize(type);
6753
7217
  return Ember.String.pluralize(decamelized);
6754
7218
  };
6755
7219
  });
6756
7220
  ```
6757
7221
 
6758
- @method rootForType
7222
+ @method pathForType
6759
7223
  @param {String} type
6760
7224
  @returns String
6761
7225
  **/
6762
- rootForType: function(type) {
7226
+ pathForType: function(type) {
6763
7227
  return Ember.String.pluralize(type);
6764
7228
  },
6765
7229
 
7230
+ /**
7231
+ Takes an ajax response, and returns a relavant error.
7232
+
7233
+ By default, it has the following behavior:
7234
+
7235
+ * It simply returns the ajax response.
7236
+
7237
+ @method ajaxError
7238
+ @param jqXHR
7239
+ */
7240
+ ajaxError: function(jqXHR) {
7241
+ if (jqXHR) {
7242
+ jqXHR.then = null;
7243
+ }
7244
+
7245
+ return jqXHR;
7246
+ },
7247
+
6766
7248
  /**
6767
7249
  Takes a URL, an HTTP method and a hash of data, and makes an
6768
7250
  HTTP request.
@@ -6790,40 +7272,43 @@ DS.RESTAdapter = DS.Adapter.extend({
6790
7272
  var adapter = this;
6791
7273
 
6792
7274
  return new Ember.RSVP.Promise(function(resolve, reject) {
6793
- hash = hash || {};
6794
- hash.url = url;
6795
- hash.type = type;
6796
- hash.dataType = 'json';
6797
- hash.context = adapter;
6798
-
6799
- if (hash.data && type !== 'GET') {
6800
- hash.contentType = 'application/json; charset=utf-8';
6801
- hash.data = JSON.stringify(hash.data);
6802
- }
6803
-
6804
- if (adapter.headers !== undefined) {
6805
- var headers = adapter.headers;
6806
- hash.beforeSend = function (xhr) {
6807
- forEach.call(Ember.keys(headers), function(key) {
6808
- xhr.setRequestHeader(key, headers[key]);
6809
- });
6810
- };
6811
- }
7275
+ hash = adapter.ajaxOptions(url, type, hash);
6812
7276
 
6813
7277
  hash.success = function(json) {
6814
7278
  Ember.run(null, resolve, json);
6815
7279
  };
6816
7280
 
6817
7281
  hash.error = function(jqXHR, textStatus, errorThrown) {
6818
- if (jqXHR) {
6819
- jqXHR.then = null;
6820
- }
6821
-
6822
- Ember.run(null, reject, jqXHR);
7282
+ Ember.run(null, reject, adapter.ajaxError(jqXHR));
6823
7283
  };
6824
7284
 
6825
7285
  Ember.$.ajax(hash);
6826
7286
  });
7287
+ },
7288
+
7289
+ ajaxOptions: function(url, type, hash) {
7290
+ hash = hash || {};
7291
+ hash.url = url;
7292
+ hash.type = type;
7293
+ hash.dataType = 'json';
7294
+ hash.context = this;
7295
+
7296
+ if (hash.data && type !== 'GET') {
7297
+ hash.contentType = 'application/json; charset=utf-8';
7298
+ hash.data = JSON.stringify(hash.data);
7299
+ }
7300
+
7301
+ if (this.headers !== undefined) {
7302
+ var headers = this.headers;
7303
+ hash.beforeSend = function (xhr) {
7304
+ forEach.call(Ember.keys(headers), function(key) {
7305
+ xhr.setRequestHeader(key, headers[key]);
7306
+ });
7307
+ };
7308
+ }
7309
+
7310
+
7311
+ return hash;
6827
7312
  }
6828
7313
 
6829
7314
  });
@@ -6845,16 +7330,20 @@ DS.RESTAdapter = DS.Adapter.extend({
6845
7330
  DS.Model.reopen({
6846
7331
 
6847
7332
  /**
6848
- Provides info about the model for debugging purposes
6849
- by grouping the properties into more semantic groups.
7333
+ Provides info about the model for debugging purposes
7334
+ by grouping the properties into more semantic groups.
7335
+
7336
+ Meant to be used by debugging tools such as the Chrome Ember Extension.
6850
7337
 
6851
- Meant to be used by debugging tools such as the Chrome Ember Extension.
7338
+ - Groups all attributes in "Attributes" group.
7339
+ - Groups all belongsTo relationships in "Belongs To" group.
7340
+ - Groups all hasMany relationships in "Has Many" group.
7341
+ - Groups all flags in "Flags" group.
7342
+ - Flags relationship CPs as expensive properties.
6852
7343
 
6853
- - Groups all attributes in "Attributes" group.
6854
- - Groups all belongsTo relationships in "Belongs To" group.
6855
- - Groups all hasMany relationships in "Has Many" group.
6856
- - Groups all flags in "Flags" group.
6857
- - Flags relationship CPs as expensive properties.
7344
+ @method _debugInfo
7345
+ @for DS.Model
7346
+ @private
6858
7347
  */
6859
7348
  _debugInfo: function() {
6860
7349
  var attributes = ['id'],
@@ -6874,7 +7363,7 @@ DS.Model.reopen({
6874
7363
  {
6875
7364
  name: 'Attributes',
6876
7365
  properties: attributes,
6877
- expand: true,
7366
+ expand: true
6878
7367
  },
6879
7368
  {
6880
7369
  name: 'Belongs To',
@@ -6919,26 +7408,6 @@ DS.Model.reopen({
6919
7408
 
6920
7409
 
6921
7410
  (function() {
6922
- //Copyright (C) 2011 by Living Social, Inc.
6923
-
6924
- //Permission is hereby granted, free of charge, to any person obtaining a copy of
6925
- //this software and associated documentation files (the "Software"), to deal in
6926
- //the Software without restriction, including without limitation the rights to
6927
- //use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
6928
- //of the Software, and to permit persons to whom the Software is furnished to do
6929
- //so, subject to the following conditions:
6930
-
6931
- //The above copyright notice and this permission notice shall be included in all
6932
- //copies or substantial portions of the Software.
6933
-
6934
- //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
6935
- //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6936
- //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
6937
- //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
6938
- //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
6939
- //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
6940
- //SOFTWARE.
6941
-
6942
7411
  /**
6943
7412
  Ember Data
6944
7413
 
@@ -6981,6 +7450,64 @@ function loadIrregular(rules, irregularPairs) {
6981
7450
  }
6982
7451
  }
6983
7452
 
7453
+ /**
7454
+ Inflector.Ember provides a mechanism for supplying inflection rules for your
7455
+ application. Ember includes a default set of inflection rules, and provides an
7456
+ API for providing additional rules.
7457
+
7458
+ Examples:
7459
+
7460
+ Creating an inflector with no rules.
7461
+
7462
+ ```js
7463
+ var inflector = new Ember.Inflector();
7464
+ ```
7465
+
7466
+ Creating an inflector with the default ember ruleset.
7467
+
7468
+ ```js
7469
+ var inflector = new Ember.Inflector(Ember.Inflector.defaultRules);
7470
+
7471
+ inflector.pluralize('cow') //=> 'kine'
7472
+ inflector.singularize('kine') //=> 'cow'
7473
+ ```
7474
+
7475
+ Creating an inflector and adding rules later.
7476
+
7477
+ ```javascript
7478
+ var inflector = Ember.Inflector.inflector;
7479
+
7480
+ inflector.pluralize('advice') // => 'advices'
7481
+ inflector.uncountable('advice');
7482
+ inflector.pluralize('advice') // => 'advice'
7483
+
7484
+ inflector.pluralize('formula') // => 'formulas'
7485
+ inflector.irregular('formula', 'formulae');
7486
+ inflector.pluralize('formula') // => 'formulae'
7487
+
7488
+ // you would not need to add these as they are the default rules
7489
+ inflector.plural(/$/, 's');
7490
+ inflector.singular(/s$/i, '');
7491
+ ```
7492
+
7493
+ Creating an inflector with a nondefault ruleset.
7494
+
7495
+ ```javascript
7496
+ var rules = {
7497
+ plurals: [ /$/, 's' ],
7498
+ singular: [ /\s$/, '' ],
7499
+ irregularPairs: [
7500
+ [ 'cow', 'kine' ]
7501
+ ],
7502
+ uncountable: [ 'fish' ]
7503
+ };
7504
+
7505
+ var inflector = new Ember.Inflector(rules);
7506
+ ```
7507
+
7508
+ @class Inflector
7509
+ @namespace Ember
7510
+ */
6984
7511
  function Inflector(ruleSet) {
6985
7512
  ruleSet = ruleSet || {};
6986
7513
  ruleSet.uncountable = ruleSet.uncountable || {};
@@ -6999,15 +7526,66 @@ function Inflector(ruleSet) {
6999
7526
  }
7000
7527
 
7001
7528
  Inflector.prototype = {
7529
+ /**
7530
+ @method plural
7531
+ @param {RegExp} regex
7532
+ @param {String} string
7533
+ */
7534
+ plural: function(regex, string) {
7535
+ this.rules.plurals.push([regex, string]);
7536
+ },
7537
+
7538
+ /**
7539
+ @method singular
7540
+ @param {RegExp} regex
7541
+ @param {String} string
7542
+ */
7543
+ singular: function(regex, string) {
7544
+ this.rules.singular.push([regex, string]);
7545
+ },
7546
+
7547
+ /**
7548
+ @method uncountable
7549
+ @param {String} regex
7550
+ */
7551
+ uncountable: function(string) {
7552
+ loadUncountable(this.rules, [string]);
7553
+ },
7554
+
7555
+ /**
7556
+ @method irregular
7557
+ @param {String} singular
7558
+ @param {String} plural
7559
+ */
7560
+ irregular: function (singular, plural) {
7561
+ loadIrregular(this.rules, [[singular, plural]]);
7562
+ },
7563
+
7564
+ /**
7565
+ @method pluralize
7566
+ @param {String} word
7567
+ */
7002
7568
  pluralize: function(word) {
7003
- return this.inflect(word, this.rules.plurals);
7569
+ return this.inflect(word, this.rules.plurals, this.rules.irregular);
7004
7570
  },
7005
7571
 
7572
+ /**
7573
+ @method singularize
7574
+ @param {String} word
7575
+ */
7006
7576
  singularize: function(word) {
7007
- return this.inflect(word, this.rules.singular);
7577
+ return this.inflect(word, this.rules.singular, this.rules.irregularInverse);
7008
7578
  },
7009
7579
 
7010
- inflect: function(word, typeRules) {
7580
+ /**
7581
+ @protected
7582
+
7583
+ @method inflect
7584
+ @param {String} word
7585
+ @param {Object} typeRules
7586
+ @param {Object} irregular
7587
+ */
7588
+ inflect: function(word, typeRules, irregular) {
7011
7589
  var inflection, substitution, result, lowercase, isBlank,
7012
7590
  isUncountable, isIrregular, isIrregularInverse, rule;
7013
7591
 
@@ -7025,18 +7603,12 @@ Inflector.prototype = {
7025
7603
  return word;
7026
7604
  }
7027
7605
 
7028
- isIrregular = this.rules.irregular[lowercase];
7606
+ isIrregular = irregular && irregular[lowercase];
7029
7607
 
7030
7608
  if (isIrregular) {
7031
7609
  return isIrregular;
7032
7610
  }
7033
7611
 
7034
- isIrregularInverse = this.rules.irregularInverse[lowercase];
7035
-
7036
- if (isIrregularInverse) {
7037
- return isIrregularInverse;
7038
- }
7039
-
7040
7612
  for (var i = typeRules.length, min = 0; i > min; i--) {
7041
7613
  inflection = typeRules[i-1];
7042
7614
  rule = inflection[0];
@@ -7148,7 +7720,7 @@ Ember.Inflector.defaultRules = {
7148
7720
 
7149
7721
 
7150
7722
  (function() {
7151
- if (Ember.EXTEND_PROTOTYPES) {
7723
+ if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.String) {
7152
7724
  /**
7153
7725
  See {{#crossLink "Ember.String/pluralize"}}{{/crossLink}}
7154
7726
 
@@ -7181,6 +7753,363 @@ Ember.Inflector.inflector = new Ember.Inflector(Ember.Inflector.defaultRules);
7181
7753
 
7182
7754
 
7183
7755
 
7756
+ (function() {
7757
+
7758
+ })();
7759
+
7760
+ (function() {
7761
+ /**
7762
+ @module ember-data
7763
+ */
7764
+
7765
+ var get = Ember.get;
7766
+ var forEach = Ember.EnumerableUtils.forEach;
7767
+
7768
+ DS.ActiveModelSerializer = DS.RESTSerializer.extend({
7769
+ // SERIALIZE
7770
+
7771
+ /**
7772
+ Converts camelcased attributes to underscored when serializing.
7773
+
7774
+ @method keyForAttribute
7775
+ @param {String} attribute
7776
+ @returns String
7777
+ */
7778
+ keyForAttribute: function(attr) {
7779
+ return Ember.String.decamelize(attr);
7780
+ },
7781
+
7782
+ /**
7783
+ Underscores relationship names and appends "_id" or "_ids" when serializing
7784
+ relationship keys.
7785
+
7786
+ @method keyForRelationship
7787
+ @param {String} key
7788
+ @param {String} kind
7789
+ @returns String
7790
+ */
7791
+ keyForRelationship: function(key, kind) {
7792
+ key = Ember.String.decamelize(key);
7793
+ if (kind === "belongsTo") {
7794
+ return key + "_id";
7795
+ } else if (kind === "hasMany") {
7796
+ return Ember.String.singularize(key) + "_ids";
7797
+ } else {
7798
+ return key;
7799
+ }
7800
+ },
7801
+
7802
+ /**
7803
+ Serialize has-may relationship when it is configured as embedded objects.
7804
+
7805
+ @method serializeHasMany
7806
+ */
7807
+ serializeHasMany: function(record, json, relationship) {
7808
+ var key = relationship.key,
7809
+ attrs = get(this, 'attrs'),
7810
+ embed = attrs && attrs[key] && attrs[key].embedded === 'always';
7811
+
7812
+ if (embed) {
7813
+ json[this.keyForAttribute(key)] = get(record, key).map(function(relation) {
7814
+ var data = relation.serialize(),
7815
+ primaryKey = get(this, 'primaryKey');
7816
+
7817
+ data[primaryKey] = get(relation, primaryKey);
7818
+
7819
+ return data;
7820
+ }, this);
7821
+ }
7822
+ },
7823
+
7824
+ /**
7825
+ Underscores the JSON root keys when serializing.
7826
+
7827
+ @method serializeIntoHash
7828
+ @param {Object} hash
7829
+ @param {subclass of DS.Model} type
7830
+ @param {DS.Model} record
7831
+ @param {Object} options
7832
+ */
7833
+ serializeIntoHash: function(data, type, record, options) {
7834
+ var root = Ember.String.decamelize(type.typeKey);
7835
+ data[root] = this.serialize(record, options);
7836
+ },
7837
+
7838
+ /**
7839
+ Serializes a polymorphic type as a fully capitalized model name.
7840
+
7841
+ @method serializePolymorphicType
7842
+ @param {DS.Model} record
7843
+ @param {Object} json
7844
+ @param relationship
7845
+ */
7846
+ serializePolymorphicType: function(record, json, relationship) {
7847
+ var key = relationship.key,
7848
+ belongsTo = get(record, key);
7849
+ key = this.keyForAttribute(key);
7850
+ json[key + "_type"] = Ember.String.capitalize(belongsTo.constructor.typeKey);
7851
+ },
7852
+
7853
+ // EXTRACT
7854
+
7855
+ /**
7856
+ Extracts the model typeKey from underscored root objects.
7857
+
7858
+ @method typeForRoot
7859
+ @param {String} root
7860
+ @returns String the model's typeKey
7861
+ */
7862
+ typeForRoot: function(root) {
7863
+ var camelized = Ember.String.camelize(root);
7864
+ return Ember.String.singularize(camelized);
7865
+ },
7866
+
7867
+ /**
7868
+ Normalize the polymorphic type from the JSON.
7869
+
7870
+ Normalize:
7871
+ ```js
7872
+ {
7873
+ id: "1"
7874
+ minion: { type: "evil_minion", id: "12"}
7875
+ }
7876
+ ```
7877
+
7878
+ To:
7879
+ ```js
7880
+ {
7881
+ id: "1"
7882
+ minion: { type: "evilMinion", id: "12"}
7883
+ }
7884
+ ```
7885
+
7886
+ @method normalizeRelationships
7887
+ @private
7888
+ */
7889
+ normalizeRelationships: function(type, hash) {
7890
+ var payloadKey, payload;
7891
+
7892
+ if (this.keyForRelationship) {
7893
+ type.eachRelationship(function(key, relationship) {
7894
+ if (relationship.options.polymorphic) {
7895
+ payloadKey = this.keyForAttribute(key);
7896
+ payload = hash[payloadKey];
7897
+ if (payload && payload.type) {
7898
+ payload.type = this.typeForRoot(payload.type);
7899
+ } else if (payload && relationship.kind === "hasMany") {
7900
+ var self = this;
7901
+ forEach(payload, function(single) {
7902
+ single.type = self.typeForRoot(single.type);
7903
+ });
7904
+ }
7905
+ } else {
7906
+ payloadKey = this.keyForRelationship(key, relationship.kind);
7907
+ payload = hash[payloadKey];
7908
+ }
7909
+
7910
+ hash[key] = payload;
7911
+
7912
+ if (key !== payloadKey) {
7913
+ delete hash[payloadKey];
7914
+ }
7915
+ }, this);
7916
+ }
7917
+ },
7918
+
7919
+ extractSingle: function(store, primaryType, payload, recordId, requestType) {
7920
+ var root = this.keyForAttribute(primaryType.typeKey),
7921
+ partial = payload[root];
7922
+
7923
+ updatePayloadWithEmbedded(store, this, primaryType, partial, payload);
7924
+
7925
+ return this._super(store, primaryType, payload, recordId, requestType);
7926
+ },
7927
+
7928
+ extractArray: function(store, type, payload) {
7929
+ var root = this.keyForAttribute(type.typeKey),
7930
+ partials = payload[Ember.String.pluralize(root)];
7931
+
7932
+ forEach(partials, function(partial) {
7933
+ updatePayloadWithEmbedded(store, this, type, partial, payload);
7934
+ }, this);
7935
+
7936
+ return this._super(store, type, payload);
7937
+ }
7938
+ });
7939
+
7940
+ function updatePayloadWithEmbedded(store, serializer, type, partial, payload) {
7941
+ var attrs = get(serializer, 'attrs');
7942
+
7943
+ if (!attrs) {
7944
+ return;
7945
+ }
7946
+
7947
+ type.eachRelationship(function(key, relationship) {
7948
+ var expandedKey, embeddedTypeKey, attribute, ids,
7949
+ config = attrs[key],
7950
+ serializer = store.serializerFor(relationship.type.typeKey),
7951
+ primaryKey = get(serializer, "primaryKey");
7952
+
7953
+ if (relationship.kind !== "hasMany") {
7954
+ return;
7955
+ }
7956
+
7957
+ if (config && (config.embedded === 'always' || config.embedded === 'load')) {
7958
+ // underscore forces the embedded records to be side loaded.
7959
+ // it is needed when main type === relationship.type
7960
+ embeddedTypeKey = '_' + Ember.String.pluralize(relationship.type.typeKey);
7961
+ expandedKey = this.keyForRelationship(key, relationship.kind);
7962
+ attribute = this.keyForAttribute(key);
7963
+ ids = [];
7964
+
7965
+ if (!partial[attribute]) {
7966
+ return;
7967
+ }
7968
+
7969
+ payload[embeddedTypeKey] = payload[embeddedTypeKey] || [];
7970
+
7971
+ forEach(partial[attribute], function(data) {
7972
+ var embeddedType = store.modelFor(relationship.type.typeKey);
7973
+ updatePayloadWithEmbedded(store, serializer, embeddedType, data, payload);
7974
+ ids.push(data[primaryKey]);
7975
+ payload[embeddedTypeKey].push(data);
7976
+ });
7977
+
7978
+ partial[expandedKey] = ids;
7979
+ delete partial[attribute];
7980
+ }
7981
+ }, serializer);
7982
+ }
7983
+
7984
+ })();
7985
+
7986
+
7987
+
7988
+ (function() {
7989
+ /**
7990
+ @module ember-data
7991
+ */
7992
+
7993
+ var forEach = Ember.EnumerableUtils.forEach;
7994
+
7995
+ /**
7996
+ The ActiveModelAdapter is a subclass of the RESTAdapter designed to integrate
7997
+ with a JSON API that uses an underscored naming convention instead of camelcasing.
7998
+ It has been designed to work out of the box with the
7999
+ [active_model_serializers](http://github.com/rails-api/active_model_serializers)
8000
+ Ruby gem.
8001
+
8002
+ ## JSON Structure
8003
+
8004
+ The ActiveModelAdapter expects the JSON returned from your server to follow
8005
+ the REST adapter conventions substituting underscored keys for camelcased ones.
8006
+
8007
+ ### Conventional Names
8008
+
8009
+ Attribute names in your JSON payload should be the underscored versions of
8010
+ the attributes in your Ember.js models.
8011
+
8012
+ For example, if you have a `Person` model:
8013
+
8014
+ ```js
8015
+ App.FamousPerson = DS.Model.extend({
8016
+ firstName: DS.attr('string'),
8017
+ lastName: DS.attr('string'),
8018
+ occupation: DS.attr('string')
8019
+ });
8020
+ ```
8021
+
8022
+ The JSON returned should look like this:
8023
+
8024
+ ```js
8025
+ {
8026
+ "famous_person": {
8027
+ "first_name": "Barack",
8028
+ "last_name": "Obama",
8029
+ "occupation": "President"
8030
+ }
8031
+ }
8032
+ ```
8033
+
8034
+ @class ActiveModelAdapter
8035
+ @constructor
8036
+ @namespace DS
8037
+ @extends DS.Adapter
8038
+ **/
8039
+
8040
+ DS.ActiveModelAdapter = DS.RESTAdapter.extend({
8041
+ defaultSerializer: '_ams',
8042
+ /**
8043
+ The ActiveModelAdapter overrides the `pathForType` method
8044
+ to build underscored URLs.
8045
+
8046
+ ```js
8047
+ this.pathForType("famousPerson");
8048
+ //=> "famous_people"
8049
+ ```
8050
+
8051
+ @method pathForType
8052
+ @param {String} type
8053
+ @returns String
8054
+ */
8055
+ pathForType: function(type) {
8056
+ var decamelized = Ember.String.decamelize(type);
8057
+ return Ember.String.pluralize(decamelized);
8058
+ },
8059
+
8060
+ /**
8061
+ The ActiveModelAdapter overrides the `ajaxError` method
8062
+ to return a DS.InvalidError for all 422 Unprocessable Entity
8063
+ responses.
8064
+
8065
+ @method ajaxError
8066
+ @param jqXHR
8067
+ @returns error
8068
+ */
8069
+ ajaxError: function(jqXHR) {
8070
+ var error = this._super(jqXHR);
8071
+
8072
+ if (jqXHR && jqXHR.status === 422) {
8073
+ var jsonErrors = Ember.$.parseJSON(jqXHR.responseText)["errors"],
8074
+ errors = {};
8075
+
8076
+ forEach(Ember.keys(jsonErrors), function(key) {
8077
+ errors[Ember.String.camelize(key)] = jsonErrors[key];
8078
+ });
8079
+
8080
+ return new DS.InvalidError(errors);
8081
+ } else {
8082
+ return error;
8083
+ }
8084
+ }
8085
+ });
8086
+
8087
+ })();
8088
+
8089
+
8090
+
8091
+ (function() {
8092
+
8093
+ })();
8094
+
8095
+
8096
+
8097
+ (function() {
8098
+ Ember.onLoad('Ember.Application', function(Application) {
8099
+ Application.initializer({
8100
+ name: "activeModelAdapter",
8101
+
8102
+ initialize: function(container, application) {
8103
+ application.register('serializer:_ams', DS.ActiveModelSerializer);
8104
+ application.register('adapter:_ams', DS.ActiveModelAdapter);
8105
+ }
8106
+ });
8107
+ });
8108
+
8109
+ })();
8110
+
8111
+
8112
+
7184
8113
  (function() {
7185
8114
 
7186
8115
  })();