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

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
  })();