diff --git a/ajax/libs/ember-data.js/0.13.0-latest20130528/ember-data-latest.js b/ajax/libs/ember-data.js/0.13.0-latest20130528/ember-data-latest.js deleted file mode 100644 index d11ec4887..000000000 --- a/ajax/libs/ember-data.js/0.13.0-latest20130528/ember-data-latest.js +++ /dev/null @@ -1,8888 +0,0 @@ -// Version: v0.13 -// Last commit: 610cfec (2013-05-28 08:04:23 -0400) - - -(function() { -var define, requireModule; - -(function() { - var registry = {}, seen = {}; - - define = function(name, deps, callback) { - registry[name] = { deps: deps, callback: callback }; - }; - - requireModule = function(name) { - if (seen[name]) { return seen[name]; } - seen[name] = {}; - - var mod = registry[name], - deps = mod.deps, - callback = mod.callback, - reified = [], - exports; - - for (var i=0, l=deps.length; i - * © 2011 Colin Snover - * Released under MIT license. - */ - -Ember.Date = Ember.Date || {}; - -var origParse = Date.parse, numericKeys = [ 1, 4, 5, 6, 7, 10, 11 ]; -Ember.Date.parse = function (date) { - var timestamp, struct, minutesOffset = 0; - - // ES5 §15.9.4.2 states that the string should attempt to be parsed as a Date Time String Format string - // before falling back to any implementation-specific date parsing, so that’s what we do, even if native - // implementations could be faster - // 1 YYYY 2 MM 3 DD 4 HH 5 mm 6 ss 7 msec 8 Z 9 ± 10 tzHH 11 tzmm - if ((struct = /^(\d{4}|[+\-]\d{6})(?:-(\d{2})(?:-(\d{2}))?)?(?:T(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{3}))?)?(?:(Z)|([+\-])(\d{2})(?::(\d{2}))?)?)?$/.exec(date))) { - // avoid NaN timestamps caused by “undefined” values being passed to Date.UTC - for (var i = 0, k; (k = numericKeys[i]); ++i) { - struct[k] = +struct[k] || 0; - } - - // allow undefined days and months - struct[2] = (+struct[2] || 1) - 1; - struct[3] = +struct[3] || 1; - - if (struct[8] !== 'Z' && struct[9] !== undefined) { - minutesOffset = struct[10] * 60 + struct[11]; - - if (struct[9] === '+') { - minutesOffset = 0 - minutesOffset; - } - } - - timestamp = Date.UTC(struct[1], struct[2], struct[3], struct[4], struct[5] + minutesOffset, struct[6], struct[7]); - } - else { - timestamp = origParse ? origParse(date) : NaN; - } - - return timestamp; -}; - -if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Date) { - Date.parse = Ember.Date.parse; -} - -})(); - - - -(function() { - -})(); - - - -(function() { -var Evented = Ember.Evented, // ember-runtime/mixins/evented - Deferred = Ember.DeferredMixin, // ember-runtime/mixins/evented - run = Ember.run, // ember-metal/run-loop - get = Ember.get; // ember-metal/accessors - -var LoadPromise = Ember.Mixin.create(Evented, Deferred, { - init: function() { - this._super.apply(this, arguments); - - this.one('didLoad', this, function() { - run(this, 'resolve', this); - }); - - this.one('becameError', this, function() { - run(this, 'reject', this); - }); - - if (get(this, 'isLoaded')) { - this.trigger('didLoad'); - } - } -}); - -DS.LoadPromise = LoadPromise; - -})(); - - - -(function() { -/** -*/ - -var get = Ember.get, set = Ember.set; - -var LoadPromise = DS.LoadPromise; // system/mixins/load_promise - -/** - A record array is an array that contains records of a certain type. The record - array materializes records as needed when they are retrieved for the first - time. You should not create record arrays yourself. Instead, an instance of - DS.RecordArray or its subclasses will be returned by your application's store - in response to queries. - - @module data - @submodule data-record-array - @main data-record-array - - @class RecordArray - @namespace DS - @extends Ember.ArrayProxy - @uses Ember.Evented - @uses DS.LoadPromise -*/ - -DS.RecordArray = Ember.ArrayProxy.extend(LoadPromise, { - /** - The model type contained by this record array. - - @type DS.Model - */ - type: null, - - // The array of client ids backing the record array. When a - // record is requested from the record array, the record - // for the client id at the same index is materialized, if - // necessary, by the store. - content: null, - - isLoaded: false, - isUpdating: false, - - // The store that created this record array. - store: null, - - objectAtContent: function(index) { - var content = get(this, 'content'), - reference = content.objectAt(index), - store = get(this, 'store'); - - if (reference) { - return store.recordForReference(reference); - } - }, - - materializedObjectAt: function(index) { - var reference = get(this, 'content').objectAt(index); - if (!reference) { return; } - - if (get(this, 'store').recordIsMaterialized(reference)) { - return this.objectAt(index); - } - }, - - update: function() { - if (get(this, 'isUpdating')) { return; } - - var store = get(this, 'store'), - type = get(this, 'type'); - - store.fetchAll(type, this); - }, - - addReference: function(reference) { - get(this, 'content').addObject(reference); - }, - - removeReference: function(reference) { - get(this, 'content').removeObject(reference); - } -}); - -})(); - - - -(function() { -/** - @module data - @submodule data-record-array -*/ - -var get = Ember.get; - -/** - @class FilteredRecordArray - @namespace DS - @extends DS.RecordArray - @constructor -*/ -DS.FilteredRecordArray = DS.RecordArray.extend({ - filterFunction: null, - isLoaded: true, - - replace: function() { - var type = get(this, 'type').toString(); - throw new Error("The result of a client-side filter (on " + type + ") is immutable."); - }, - - updateFilter: Ember.observer(function() { - var manager = get(this, 'manager'); - manager.updateFilter(this, get(this, 'type'), get(this, 'filterFunction')); - }, 'filterFunction') -}); - -})(); - - - -(function() { -/** - @module data - @submodule data-record-array -*/ - -var get = Ember.get, set = Ember.set; - -/** - @class AdapterPopulatedRecordArray - @namespace DS - @extends DS.RecordArray - @constructor -*/ -DS.AdapterPopulatedRecordArray = DS.RecordArray.extend({ - query: null, - - replace: function() { - var type = get(this, 'type').toString(); - throw new Error("The result of a server query (on " + type + ") is immutable."); - }, - - load: function(references) { - this.setProperties({ - content: Ember.A(references), - isLoaded: true - }); - - // TODO: does triggering didLoad event should be the last action of the runLoop? - Ember.run.once(this, 'trigger', 'didLoad'); - } -}); - -})(); - - - -(function() { -/** - @module data - @submodule data-record-array -*/ - -var get = Ember.get, set = Ember.set; - -/** - A ManyArray is a RecordArray that represents the contents of a has-many - relationship. - - The ManyArray is instantiated lazily the first time the relationship is - requested. - - ### Inverses - - Often, the relationships in Ember Data applications will have - an inverse. For example, imagine the following models are - defined: - - App.Post = DS.Model.extend({ - comments: DS.hasMany('App.Comment') - }); - - App.Comment = DS.Model.extend({ - post: DS.belongsTo('App.Post') - }); - - If you created a new instance of `App.Post` and added - a `App.Comment` record to its `comments` has-many - relationship, you would expect the comment's `post` - property to be set to the post that contained - the has-many. - - We call the record to which a relationship belongs the - relationship's _owner_. - - @class ManyArray - @namespace DS - @extends DS.RecordArray - @constructor -*/ -DS.ManyArray = DS.RecordArray.extend({ - init: function() { - this._super.apply(this, arguments); - this._changesToSync = Ember.OrderedSet.create(); - }, - - /** - @private - - The record to which this relationship belongs. - - @property {DS.Model} - */ - owner: null, - - /** - @private - - `true` if the relationship is polymorphic, `false` otherwise. - - @property {Boolean} - */ - isPolymorphic: false, - - // LOADING STATE - - isLoaded: false, - - loadingRecordsCount: function(count) { - this.loadingRecordsCount = count; - }, - - loadedRecord: function() { - this.loadingRecordsCount--; - if (this.loadingRecordsCount === 0) { - set(this, 'isLoaded', true); - this.trigger('didLoad'); - } - }, - - fetch: function() { - var references = get(this, 'content'), - store = get(this, 'store'), - owner = get(this, 'owner'); - - store.fetchUnloadedReferences(references, owner); - }, - - // Overrides Ember.Array's replace method to implement - replaceContent: function(index, removed, added) { - // Map the array of record objects into an array of client ids. - added = added.map(function(record) { - Ember.assert("You can only add records of " + (get(this, 'type') && get(this, 'type').toString()) + " to this relationship.", !get(this, 'type') || (get(this, 'type').detectInstance(record)) ); - return get(record, '_reference'); - }, this); - - this._super(index, removed, added); - }, - - arrangedContentDidChange: function() { - this.fetch(); - }, - - arrayContentWillChange: function(index, removed, added) { - var owner = get(this, 'owner'), - name = get(this, 'name'); - - if (!owner._suspendedRelationships) { - // This code is the first half of code that continues inside - // of arrayContentDidChange. It gets or creates a change from - // the child object, adds the current owner as the old - // parent if this is the first time the object was removed - // from a ManyArray, and sets `newParent` to null. - // - // Later, if the object is added to another ManyArray, - // the `arrayContentDidChange` will set `newParent` on - // the change. - for (var i=index; i "created.uncommitted" - - The `DS.Model` states are themselves stateless. What we mean is that, - though each instance of a record also has a unique instance of a - `DS.StateManager`, the hierarchical states that each of *those* points - to is a shared data structure. For performance reasons, instead of each - record getting its own copy of the hierarchy of states, each state - manager points to this global, immutable shared instance. How does a - state know which record it should be acting on? We pass a reference to - the current state manager as the first parameter to every method invoked - on a state. - - The state manager passed as the first parameter is where you should stash - state about the record if needed; you should never store data on the state - object itself. If you need access to the record being acted on, you can - retrieve the state manager's `record` property. For example, if you had - an event handler `myEvent`: - - myEvent: function(manager) { - var record = manager.get('record'); - record.doSomething(); - } - - For more information about state managers in general, see the Ember.js - documentation on `Ember.StateManager`. - - ### Events, Flags, and Transitions - - A state may implement zero or more events, flags, or transitions. - - #### Events - - Events are named functions that are invoked when sent to a record. The - state manager will first look for a method with the given name on the - current state. If no method is found, it will search the current state's - parent, and then its grandparent, and so on until reaching the top of - the hierarchy. If the root is reached without an event handler being found, - an exception will be raised. This can be very helpful when debugging new - features. - - Here's an example implementation of a state with a `myEvent` event handler: - - aState: DS.State.create({ - myEvent: function(manager, param) { - console.log("Received myEvent with "+param); - } - }) - - To trigger this event: - - record.send('myEvent', 'foo'); - //=> "Received myEvent with foo" - - Note that an optional parameter can be sent to a record's `send()` method, - which will be passed as the second parameter to the event handler. - - Events should transition to a different state if appropriate. This can be - done by calling the state manager's `transitionTo()` method with a path to the - desired state. The state manager will attempt to resolve the state path - relative to the current state. If no state is found at that path, it will - attempt to resolve it relative to the current state's parent, and then its - parent, and so on until the root is reached. For example, imagine a hierarchy - like this: - - * created - * start <-- currentState - * inFlight - * updated - * inFlight - - If we are currently in the `start` state, calling - `transitionTo('inFlight')` would transition to the `created.inFlight` state, - while calling `transitionTo('updated.inFlight')` would transition to - the `updated.inFlight` state. - - Remember that *only events* should ever cause a state transition. You should - never call `transitionTo()` from outside a state's event handler. If you are - tempted to do so, create a new event and send that to the state manager. - - #### Flags - - Flags are Boolean values that can be used to introspect a record's current - state in a more user-friendly way than examining its state path. For example, - instead of doing this: - - var statePath = record.get('stateManager.currentPath'); - if (statePath === 'created.inFlight') { - doSomething(); - } - - You can say: - - if (record.get('isNew') && record.get('isSaving')) { - doSomething(); - } - - If your state does not set a value for a given flag, the value will - be inherited from its parent (or the first place in the state hierarchy - where it is defined). - - The current set of flags are defined below. If you want to add a new flag, - in addition to the area below, you will also need to declare it in the - `DS.Model` class. - - #### Transitions - - Transitions are like event handlers but are called automatically upon - entering or exiting a state. To implement a transition, just call a method - either `enter` or `exit`: - - myState: DS.State.create({ - // Gets called automatically when entering - // this state. - enter: function(manager) { - console.log("Entered myState"); - } - }) - - Note that enter and exit events are called once per transition. If the - current state changes, but changes to another child state of the parent, - the transition event on the parent will not be triggered. - - @class States - @namespace DS - @extends Ember.State -*/ - -var stateProperty = Ember.computed(function(key) { - var parent = get(this, 'parentState'); - if (parent) { - return get(parent, key); - } -}).property(); - -var hasDefinedProperties = function(object) { - for (var name in object) { - if (object.hasOwnProperty(name) && object[name]) { return true; } - } - - return false; -}; - -var didChangeData = function(manager) { - var record = get(manager, 'record'); - record.materializeData(); -}; - -var willSetProperty = function(manager, context) { - context.oldValue = get(get(manager, 'record'), context.name); - - var change = DS.AttributeChange.createChange(context); - get(manager, 'record')._changesToSync[context.name] = change; -}; - -var didSetProperty = function(manager, context) { - var change = get(manager, 'record')._changesToSync[context.name]; - change.value = get(get(manager, 'record'), context.name); - change.sync(); -}; - -DS.State = Ember.State.extend({ - isLoading: stateProperty, - isLoaded: stateProperty, - isReloading: stateProperty, - isDirty: stateProperty, - isSaving: stateProperty, - isDeleted: stateProperty, - isError: stateProperty, - isNew: stateProperty, - isValid: stateProperty, - - // For states that are substates of a - // DirtyState (updated or created), it is - // useful to be able to determine which - // type of dirty state it is. - dirtyType: stateProperty -}); - -// Implementation notes: -// -// Each state has a boolean value for all of the following flags: -// -// * isLoaded: The record has a populated `data` property. When a -// record is loaded via `store.find`, `isLoaded` is false -// until the adapter sets it. When a record is created locally, -// its `isLoaded` property is always true. -// * isDirty: The record has local changes that have not yet been -// saved by the adapter. This includes records that have been -// created (but not yet saved) or deleted. -// * isSaving: The record's transaction has been committed, but -// the adapter has not yet acknowledged that the changes have -// been persisted to the backend. -// * isDeleted: The record was marked for deletion. When `isDeleted` -// is true and `isDirty` is true, the record is deleted locally -// but the deletion was not yet persisted. When `isSaving` is -// true, the change is in-flight. When both `isDirty` and -// `isSaving` are false, the change has persisted. -// * isError: The adapter reported that it was unable to save -// local changes to the backend. This may also result in the -// record having its `isValid` property become false if the -// adapter reported that server-side validations failed. -// * isNew: The record was created on the client and the adapter -// did not yet report that it was successfully saved. -// * isValid: No client-side validations have failed and the -// adapter did not report any server-side validation failures. - -// The dirty state is a abstract state whose functionality is -// shared between the `created` and `updated` states. -// -// The deleted state shares the `isDirty` flag with the -// subclasses of `DirtyState`, but with a very different -// implementation. -// -// Dirty states have three child states: -// -// `uncommitted`: the store has not yet handed off the record -// to be saved. -// `inFlight`: the store has handed off the record to be saved, -// but the adapter has not yet acknowledged success. -// `invalid`: the record has invalid information and cannot be -// send to the adapter yet. -var DirtyState = DS.State.extend({ - initialState: 'uncommitted', - - // FLAGS - isDirty: true, - - // SUBSTATES - - // When a record first becomes dirty, it is `uncommitted`. - // This means that there are local pending changes, but they - // have not yet begun to be saved, and are not invalid. - uncommitted: DS.State.extend({ - - // EVENTS - willSetProperty: willSetProperty, - didSetProperty: didSetProperty, - - becomeDirty: Ember.K, - - willCommit: function(manager) { - manager.transitionTo('inFlight'); - }, - - becameClean: function(manager) { - var record = get(manager, 'record'); - - record.withTransaction(function(t) { - t.remove(record); - }); - manager.transitionTo('loaded.materializing'); - }, - - becameInvalid: function(manager) { - manager.transitionTo('invalid'); - }, - - rollback: function(manager) { - get(manager, 'record').rollback(); - } - }), - - // Once a record has been handed off to the adapter to be - // saved, it is in the 'in flight' state. Changes to the - // record cannot be made during this window. - inFlight: DS.State.extend({ - // FLAGS - isSaving: true, - - // TRANSITIONS - enter: function(manager) { - var record = get(manager, 'record'); - - record.becameInFlight(); - }, - - // EVENTS - - materializingData: function(manager) { - set(manager, 'lastDirtyType', get(this, 'dirtyType')); - manager.transitionTo('materializing'); - }, - - didCommit: function(manager) { - var dirtyType = get(this, 'dirtyType'), - record = get(manager, 'record'); - - record.withTransaction(function(t) { - t.remove(record); - }); - - manager.transitionTo('saved'); - manager.send('invokeLifecycleCallbacks', dirtyType); - }, - - didChangeData: didChangeData, - - becameInvalid: function(manager, errors) { - var record = get(manager, 'record'); - - set(record, 'errors', errors); - - manager.transitionTo('invalid'); - manager.send('invokeLifecycleCallbacks'); - }, - - becameError: function(manager) { - manager.transitionTo('error'); - manager.send('invokeLifecycleCallbacks'); - } - }), - - // A record is in the `invalid` state when its client-side - // invalidations have failed, or if the adapter has indicated - // the the record failed server-side invalidations. - invalid: DS.State.extend({ - // FLAGS - isValid: false, - - exit: function(manager) { - var record = get(manager, 'record'); - - record.withTransaction(function (t) { - t.remove(record); - }); - }, - - // EVENTS - deleteRecord: function(manager) { - manager.transitionTo('deleted'); - get(manager, 'record').clearRelationships(); - }, - - willSetProperty: willSetProperty, - - didSetProperty: function(manager, context) { - var record = get(manager, 'record'), - errors = get(record, 'errors'), - key = context.name; - - set(errors, key, null); - - if (!hasDefinedProperties(errors)) { - manager.send('becameValid'); - } - - didSetProperty(manager, context); - }, - - becomeDirty: Ember.K, - - rollback: function(manager) { - manager.send('becameValid'); - manager.send('rollback'); - }, - - becameValid: function(manager) { - manager.transitionTo('uncommitted'); - }, - - invokeLifecycleCallbacks: function(manager) { - var record = get(manager, 'record'); - record.trigger('becameInvalid', record); - } - }) -}); - -// The created and updated states are created outside the state -// chart so we can reopen their substates and add mixins as -// necessary. - -var createdState = DirtyState.create({ - dirtyType: 'created', - - // FLAGS - isNew: true -}); - -var updatedState = DirtyState.create({ - dirtyType: 'updated' -}); - -createdState.states.uncommitted.reopen({ - deleteRecord: function(manager) { - var record = get(manager, 'record'); - - record.clearRelationships(); - manager.transitionTo('deleted.saved'); - } -}); - -createdState.states.uncommitted.reopen({ - rollback: function(manager) { - this._super(manager); - manager.transitionTo('deleted.saved'); - } -}); - -updatedState.states.uncommitted.reopen({ - deleteRecord: function(manager) { - var record = get(manager, 'record'); - - manager.transitionTo('deleted'); - record.clearRelationships(); - } -}); - -var states = { - rootState: Ember.State.create({ - // FLAGS - isLoading: false, - isLoaded: false, - isReloading: false, - isDirty: false, - isSaving: false, - isDeleted: false, - isError: false, - isNew: false, - isValid: true, - - // SUBSTATES - - // A record begins its lifecycle in the `empty` state. - // If its data will come from the adapter, it will - // transition into the `loading` state. Otherwise, if - // the record is being created on the client, it will - // transition into the `created` state. - empty: DS.State.create({ - // EVENTS - loadingData: function(manager) { - manager.transitionTo('loading'); - }, - - loadedData: function(manager) { - manager.transitionTo('loaded.created'); - } - }), - - // A record enters this state when the store askes - // the adapter for its data. It remains in this state - // until the adapter provides the requested data. - // - // Usually, this process is asynchronous, using an - // XHR to retrieve the data. - loading: DS.State.create({ - // FLAGS - isLoading: true, - - // EVENTS - loadedData: didChangeData, - - materializingData: function(manager) { - manager.transitionTo('loaded.materializing.firstTime'); - }, - - becameError: function(manager) { - manager.transitionTo('error'); - manager.send('invokeLifecycleCallbacks'); - } - }), - - // A record enters this state when its data is populated. - // Most of a record's lifecycle is spent inside substates - // of the `loaded` state. - loaded: DS.State.create({ - initialState: 'saved', - - // FLAGS - isLoaded: true, - - // SUBSTATES - - materializing: DS.State.create({ - // EVENTS - willSetProperty: Ember.K, - didSetProperty: Ember.K, - - didChangeData: didChangeData, - - finishedMaterializing: function(manager) { - manager.transitionTo('loaded.saved'); - }, - - // SUBSTATES - firstTime: DS.State.create({ - // FLAGS - isLoaded: false, - - exit: function(manager) { - var record = get(manager, 'record'); - - once(function() { - record.trigger('didLoad'); - }); - } - }) - }), - - reloading: DS.State.create({ - // FLAGS - isReloading: true, - - // TRANSITIONS - enter: function(manager) { - var record = get(manager, 'record'), - store = get(record, 'store'); - - store.reloadRecord(record); - }, - - exit: function(manager) { - var record = get(manager, 'record'); - - once(record, 'trigger', 'didReload'); - }, - - // EVENTS - loadedData: didChangeData, - - materializingData: function(manager) { - manager.transitionTo('loaded.materializing'); - } - }), - - // If there are no local changes to a record, it remains - // in the `saved` state. - saved: DS.State.create({ - // EVENTS - willSetProperty: willSetProperty, - didSetProperty: didSetProperty, - - didChangeData: didChangeData, - loadedData: didChangeData, - - reloadRecord: function(manager) { - manager.transitionTo('loaded.reloading'); - }, - - materializingData: function(manager) { - manager.transitionTo('loaded.materializing'); - }, - - becomeDirty: function(manager) { - manager.transitionTo('updated'); - }, - - deleteRecord: function(manager) { - manager.transitionTo('deleted'); - get(manager, 'record').clearRelationships(); - }, - - unloadRecord: function(manager) { - var record = get(manager, 'record'); - - // clear relationships before moving to deleted state - // otherwise it fails - record.clearRelationships(); - manager.transitionTo('deleted.saved'); - }, - - didCommit: function(manager) { - var record = get(manager, 'record'); - - record.withTransaction(function(t) { - t.remove(record); - }); - - manager.send('invokeLifecycleCallbacks', get(manager, 'lastDirtyType')); - }, - - invokeLifecycleCallbacks: function(manager, dirtyType) { - var record = get(manager, 'record'); - if (dirtyType === 'created') { - record.trigger('didCreate', record); - } else { - record.trigger('didUpdate', record); - } - - record.trigger('didCommit', record); - } - }), - - // A record is in this state after it has been locally - // created but before the adapter has indicated that - // it has been saved. - created: createdState, - - // A record is in this state if it has already been - // saved to the server, but there are new local changes - // that have not yet been saved. - updated: updatedState - }), - - // A record is in this state if it was deleted from the store. - deleted: DS.State.create({ - initialState: 'uncommitted', - dirtyType: 'deleted', - - // FLAGS - isDeleted: true, - isLoaded: true, - isDirty: true, - - // TRANSITIONS - setup: function(manager) { - var record = get(manager, 'record'), - store = get(record, 'store'); - - store.recordArrayManager.remove(record); - }, - - // SUBSTATES - - // When a record is deleted, it enters the `start` - // state. It will exit this state when the record's - // transaction starts to commit. - uncommitted: DS.State.create({ - - // EVENTS - willCommit: function(manager) { - manager.transitionTo('inFlight'); - }, - - rollback: function(manager) { - get(manager, 'record').rollback(); - }, - - becomeDirty: Ember.K, - - becameClean: function(manager) { - var record = get(manager, 'record'); - - record.withTransaction(function(t) { - t.remove(record); - }); - manager.transitionTo('loaded.materializing'); - } - }), - - // After a record's transaction is committing, but - // before the adapter indicates that the deletion - // has saved to the server, a record is in the - // `inFlight` substate of `deleted`. - inFlight: DS.State.create({ - // FLAGS - isSaving: true, - - // TRANSITIONS - enter: function(manager) { - var record = get(manager, 'record'); - - record.becameInFlight(); - }, - - // EVENTS - didCommit: function(manager) { - var record = get(manager, 'record'); - - record.withTransaction(function(t) { - t.remove(record); - }); - - manager.transitionTo('saved'); - - manager.send('invokeLifecycleCallbacks'); - } - }), - - // Once the adapter indicates that the deletion has - // been saved, the record enters the `saved` substate - // of `deleted`. - saved: DS.State.create({ - // FLAGS - isDirty: false, - - setup: function(manager) { - var record = get(manager, 'record'), - store = get(record, 'store'); - - store.dematerializeRecord(record); - }, - - invokeLifecycleCallbacks: function(manager) { - var record = get(manager, 'record'); - record.trigger('didDelete', record); - record.trigger('didCommit', record); - } - }) - }), - - // If the adapter indicates that there was an unknown - // error saving a record, the record enters the `error` - // state. - error: DS.State.create({ - isError: true, - - // EVENTS - - invokeLifecycleCallbacks: function(manager) { - var record = get(manager, 'record'); - record.trigger('becameError', record); - } - }) - }) -}; - -DS.StateManager = Ember.StateManager.extend({ - record: null, - initialState: 'rootState', - states: states, - unhandledEvent: function(manager, originalEvent) { - var record = manager.get('record'), - contexts = [].slice.call(arguments, 2), - errorMessage; - errorMessage = "Attempted to handle event `" + originalEvent + "` "; - errorMessage += "on " + record.toString() + " while in state "; - errorMessage += get(manager, 'currentState.path') + ". Called with "; - errorMessage += arrayMap.call(contexts, function(context){ - return Ember.inspect(context); - }).join(', '); - throw new Ember.Error(errorMessage); - } -}); - -})(); - - - -(function() { -var LoadPromise = DS.LoadPromise; // system/mixins/load_promise - -var get = Ember.get, set = Ember.set, map = Ember.EnumerableUtils.map; - -var retrieveFromCurrentState = Ember.computed(function(key, value) { - return get(get(this, 'stateManager.currentState'), key); -}).property('stateManager.currentState').readOnly(); - -/** - - The model class that all Ember Data records descend from. - - @module data - @submodule data-model - @main data-model - - @class Model - @namespace DS - @extends Ember.Object - @constructor -*/ - -DS.Model = Ember.Object.extend(Ember.Evented, LoadPromise, { - isLoading: retrieveFromCurrentState, - isLoaded: retrieveFromCurrentState, - isReloading: retrieveFromCurrentState, - isDirty: retrieveFromCurrentState, - isSaving: retrieveFromCurrentState, - isDeleted: retrieveFromCurrentState, - isError: retrieveFromCurrentState, - isNew: retrieveFromCurrentState, - isValid: retrieveFromCurrentState, - dirtyType: retrieveFromCurrentState, - - clientId: null, - id: null, - transaction: null, - stateManager: null, - errors: null, - - /** - Create a JSON representation of the record, using the serialization - strategy of the store's adapter. - - @method serialize - @param {Object} options Available options: - - * `includeId`: `true` if the record's ID should be included in the - JSON representation. - - @returns {Object} an object whose values are primitive JSON values only - */ - serialize: function(options) { - var store = get(this, 'store'); - return store.serialize(this, options); - }, - - /** - Use {{#crossLink "DS.JSONSerializer"}}DS.JSONSerializer{{/crossLink}} to - get the JSON representation of a record. - - @method toJSON - @param {Object} options Available options: - - * `includeId`: `true` if the record's ID should be included in the - JSON representation. - - @returns {Object} A JSON representation of the object. - */ - toJSON: function(options) { - var serializer = DS.JSONSerializer.create(); - return serializer.serialize(this, options); - }, - - /** - Fired when the record is loaded from the server. - - @event didLoad - */ - didLoad: Ember.K, - - /** - Fired when the record is reloaded from the server. - - @event didReload - */ - didReload: Ember.K, - - /** - Fired when the record is updated. - - @event didUpdate - */ - didUpdate: Ember.K, - - /** - Fired when the record is created. - - @event didCreate - */ - didCreate: Ember.K, - - /** - Fired when the record is deleted. - - @event didDelete - */ - didDelete: Ember.K, - - /** - Fired when the record becomes invalid. - - @event becameInvalid - */ - becameInvalid: Ember.K, - - /** - Fired when the record enters the error state. - - @event becameError - */ - becameError: Ember.K, - - data: Ember.computed(function() { - if (!this._data) { - this.setupData(); - } - - return this._data; - }).property(), - - materializeData: function() { - this.send('materializingData'); - - get(this, 'store').materializeData(this); - - this.suspendRelationshipObservers(function() { - this.notifyPropertyChange('data'); - }); - }, - - _data: null, - - init: function() { - this._super(); - - var stateManager = DS.StateManager.create({ record: this }); - set(this, 'stateManager', stateManager); - - this._setup(); - - stateManager.goToState('empty'); - }, - - _setup: function() { - this._changesToSync = {}; - }, - - send: function(name, context) { - return get(this, 'stateManager').send(name, context); - }, - - withTransaction: function(fn) { - var transaction = get(this, 'transaction'); - if (transaction) { fn(transaction); } - }, - - loadingData: function() { - this.send('loadingData'); - }, - - loadedData: function() { - this.send('loadedData'); - }, - - didChangeData: function() { - this.send('didChangeData'); - }, - - deleteRecord: function() { - this.send('deleteRecord'); - }, - - unloadRecord: function() { - Ember.assert("You can only unload a loaded, non-dirty record.", !get(this, 'isDirty')); - - this.send('unloadRecord'); - }, - - clearRelationships: function() { - this.eachRelationship(function(name, relationship) { - if (relationship.kind === 'belongsTo') { - set(this, name, null); - } else if (relationship.kind === 'hasMany') { - this.clearHasMany(relationship); - } - }, this); - }, - - updateRecordArrays: function() { - var store = get(this, 'store'); - if (store) { - store.dataWasUpdated(this.constructor, get(this, '_reference'), this); - } - }, - - /** - If the adapter did not return a hash in response to a commit, - merge the changed attributes and relationships into the existing - saved data. - */ - adapterDidCommit: function() { - var attributes = get(this, 'data').attributes; - - get(this.constructor, 'attributes').forEach(function(name, meta) { - attributes[name] = get(this, name); - }, this); - - this.send('didCommit'); - this.updateRecordArraysLater(); - }, - - adapterDidDirty: function() { - this.send('becomeDirty'); - this.updateRecordArraysLater(); - }, - - dataDidChange: Ember.observer(function() { - this.reloadHasManys(); - this.send('finishedMaterializing'); - }, 'data'), - - reloadHasManys: function() { - var relationships = get(this.constructor, 'relationshipsByName'); - this.updateRecordArraysLater(); - relationships.forEach(function(name, relationship) { - if (relationship.kind === 'hasMany') { - this.hasManyDidChange(relationship.key); - } - }, this); - }, - - hasManyDidChange: function(key) { - var cachedValue = this.cacheFor(key); - - if (cachedValue) { - var type = get(this.constructor, 'relationshipsByName').get(key).type; - var store = get(this, 'store'); - var ids = this._data.hasMany[key] || []; - - var references = map(ids, function(id) { - if (typeof id === 'object') { - if( id.clientId ) { - // if it was already a reference, return the reference - return id; - } else { - // tuple for a polymorphic association. - return store.referenceForId(id.type, id.id); - } - } - return store.referenceForId(type, id); - }); - - set(cachedValue, 'content', Ember.A(references)); - } - }, - - updateRecordArraysLater: function() { - Ember.run.once(this, this.updateRecordArrays); - }, - - setupData: function() { - this._data = { - attributes: {}, - belongsTo: {}, - hasMany: {}, - id: null - }; - }, - - materializeId: function(id) { - set(this, 'id', id); - }, - - materializeAttributes: function(attributes) { - Ember.assert("Must pass a hash of attributes to materializeAttributes", !!attributes); - this._data.attributes = attributes; - }, - - materializeAttribute: function(name, value) { - this._data.attributes[name] = value; - }, - - materializeHasMany: function(name, tuplesOrReferencesOrOpaque) { - var tuplesOrReferencesOrOpaqueType = typeof tuplesOrReferencesOrOpaque; - if (tuplesOrReferencesOrOpaque && tuplesOrReferencesOrOpaqueType !== 'string' && tuplesOrReferencesOrOpaque.length > 1) { Ember.assert('materializeHasMany expects tuples, references or opaque token, not ' + tuplesOrReferencesOrOpaque[0], tuplesOrReferencesOrOpaque[0].hasOwnProperty('id') && tuplesOrReferencesOrOpaque[0].type); } - if( tuplesOrReferencesOrOpaqueType === "string" ) { - this._data.hasMany[name] = tuplesOrReferencesOrOpaque; - } else { - var references = tuplesOrReferencesOrOpaque; - - if (tuplesOrReferencesOrOpaque && Ember.isArray(tuplesOrReferencesOrOpaque)) { - references = this._convertTuplesToReferences(tuplesOrReferencesOrOpaque); - } - - this._data.hasMany[name] = references; - } - }, - - materializeBelongsTo: function(name, tupleOrReference) { - if (tupleOrReference) { Ember.assert('materializeBelongsTo expects a tuple or a reference, not a ' + tupleOrReference, !tupleOrReference || (tupleOrReference.hasOwnProperty('id') && tupleOrReference.hasOwnProperty('type'))); } - - this._data.belongsTo[name] = tupleOrReference; - }, - - _convertTuplesToReferences: function(tuplesOrReferences) { - return map(tuplesOrReferences, function(tupleOrReference) { - return this._convertTupleToReference(tupleOrReference); - }, this); - }, - - _convertTupleToReference: function(tupleOrReference) { - var store = get(this, 'store'); - if(tupleOrReference.clientId) { - return tupleOrReference; - } else { - return store.referenceForId(tupleOrReference.type, tupleOrReference.id); - } - }, - - rollback: function() { - this._setup(); - this.send('becameClean'); - - this.suspendRelationshipObservers(function() { - this.notifyPropertyChange('data'); - }); - }, - - toStringExtension: function() { - return get(this, 'id'); - }, - - /** - @private - - The goal of this method is to temporarily disable specific observers - that take action in response to application changes. - - This allows the system to make changes (such as materialization and - rollback) that should not trigger secondary behavior (such as setting an - inverse relationship or marking records as dirty). - - The specific implementation will likely change as Ember proper provides - better infrastructure for suspending groups of observers, and if Array - observation becomes more unified with regular observers. - */ - suspendRelationshipObservers: function(callback, binding) { - var observers = get(this.constructor, 'relationshipNames').belongsTo; - var self = this; - - try { - this._suspendedRelationships = true; - Ember._suspendObservers(self, observers, null, 'belongsToDidChange', function() { - Ember._suspendBeforeObservers(self, observers, null, 'belongsToWillChange', function() { - callback.call(binding || self); - }); - }); - } finally { - this._suspendedRelationships = false; - } - }, - - becameInFlight: function() { - }, - - /** - @private - - */ - resolveOn: function(successEvent) { - var model = this; - - return new Ember.RSVP.Promise(function(resolve, reject) { - function success() { - this.off('becameError', error); - this.off('becameInvalid', error); - resolve(this); - } - function error() { - this.off(successEvent, success); - reject(this); - } - - model.one(successEvent, success); - model.one('becameError', error); - model.one('becameInvalid', error); - }); - }, - - /** - Save the record. - - @method save - */ - save: function() { - this.get('store').scheduleSave(this); - - return this.resolveOn('didCommit'); - }, - - /** - Reload the record from the adapter. - - This will only work if the record has already finished loading - and has not yet been modified (`isLoaded` but not `isDirty`, - or `isSaving`). - - @method reload - */ - reload: function() { - this.send('reloadRecord'); - - return this.resolveOn('didReload'); - }, - - // FOR USE DURING COMMIT PROCESS - - adapterDidUpdateAttribute: function(attributeName, value) { - - // If a value is passed in, update the internal attributes and clear - // the attribute cache so it picks up the new value. Otherwise, - // collapse the current value into the internal attributes because - // the adapter has acknowledged it. - if (value !== undefined) { - get(this, 'data.attributes')[attributeName] = value; - this.notifyPropertyChange(attributeName); - } else { - value = get(this, attributeName); - get(this, 'data.attributes')[attributeName] = value; - } - - this.updateRecordArraysLater(); - }, - - adapterDidInvalidate: function(errors) { - this.send('becameInvalid', errors); - }, - - adapterDidError: function() { - this.send('becameError'); - }, - - /** - @private - - Override the default event firing from Ember.Evented to - also call methods with the given name. - */ - trigger: function(name) { - Ember.tryInvoke(this, name, [].slice.call(arguments, 1)); - this._super.apply(this, arguments); - } -}); - -// Helper function to generate store aliases. -// This returns a function that invokes the named alias -// on the default store, but injects the class as the -// first parameter. -var storeAlias = function(methodName) { - return function() { - var store = get(DS, 'defaultStore'), - args = [].slice.call(arguments); - - args.unshift(this); - Ember.assert("Your application does not have a 'Store' property defined. Attempts to call '" + methodName + "' on model classes will fail. Please provide one as with 'YourAppName.Store = DS.Store.extend()'", !!store); - return store[methodName].apply(store, args); - }; -}; - -DS.Model.reopenClass({ - - /** @private - Alias DS.Model's `create` method to `_create`. This allows us to create DS.Model - instances from within the store, but if end users accidentally call `create()` - (instead of `createRecord()`), we can raise an error. - */ - _create: DS.Model.create, - - /** @private - - Override the class' `create()` method to raise an error. This prevents end users - from inadvertently calling `create()` instead of `createRecord()`. The store is - still able to create instances by calling the `_create()` method. - */ - create: function() { - throw new Ember.Error("You should not call `create` on a model. Instead, call `createRecord` with the attributes you would like to set."); - }, - - /** - See {{#crossLink "DS.Store/find:method"}}`DS.Store.find()`{{/crossLink}}. - - @method find - @param {Object|String|Array|null} query A query to find records by. - - */ - find: storeAlias('find'), - - /** - See {{#crossLink "DS.Store/all:method"}}`DS.Store.all()`{{/crossLink}}. - - @method all - @return {DS.RecordArray} - */ - all: storeAlias('all'), - - /** - See {{#crossLink "DS.Store/findQuery:method"}}`DS.Store.findQuery()`{{/crossLink}}. - - @method query - @param {Object} query an opaque query to be used by the adapter - @return {DS.AdapterPopulatedRecordArray} - */ - query: storeAlias('findQuery'), - - /** - See {{#crossLink "DS.Store/filter:method"}}`DS.Store.filter()`{{/crossLink}}. - - @method filter - @param {Function} filter - @return {DS.FilteredRecordArray} - */ - filter: storeAlias('filter'), - - /** - See {{#crossLink "DS.Store/createRecord:method"}}`DS.Store.createRecord()`{{/crossLink}}. - - @method createRecord - @param {Object} properties a hash of properties to set on the - newly created record. - @returns DS.Model - */ - createRecord: storeAlias('createRecord') -}); - -})(); - - - -(function() { -/** - @module data - @submodule data-model -*/ - -var get = Ember.get; - -DS.Model.reopenClass({ - attributes: Ember.computed(function() { - var map = Ember.Map.create(); - - this.eachComputedProperty(function(name, meta) { - if (meta.isAttribute) { - Ember.assert("You may not set `id` as an attribute on your model. Please remove any lines that look like: `id: DS.attr('')` from " + this.toString(), name !== 'id'); - - meta.name = name; - map.set(name, meta); - } - }); - - return map; - }) -}); - - -DS.Model.reopen({ - eachAttribute: function(callback, binding) { - get(this.constructor, 'attributes').forEach(function(name, meta) { - callback.call(binding, name, meta); - }, binding); - }, - - attributeWillChange: Ember.beforeObserver(function(record, key) { - var reference = get(record, '_reference'), - store = get(record, 'store'); - - record.send('willSetProperty', { reference: reference, store: store, name: key }); - }), - - attributeDidChange: Ember.observer(function(record, key) { - record.send('didSetProperty', { name: key }); - }) -}); - -function getAttr(record, options, key) { - var attributes = get(record, 'data').attributes; - var value = attributes[key]; - - if (value === undefined) { - if (typeof options.defaultValue === "function") { - value = options.defaultValue(); - } else { - value = options.defaultValue; - } - } - - return value; -} - -DS.attr = function(type, options) { - options = options || {}; - - var meta = { - type: type, - isAttribute: true, - options: options - }; - - return Ember.computed(function(key, value, oldValue) { - if (arguments.length > 1) { - Ember.assert("You may not set `id` as an attribute on your model. Please remove any lines that look like: `id: DS.attr('')` from " + this.constructor.toString(), key !== 'id'); - } else { - value = getAttr(this, options, key); - } - - return value; - // `data` is never set directly. However, it may be - // invalidated from the state manager's setData - // event. - }).property('data').meta(meta); -}; - - -})(); - - - -(function() { -/** - @module data - @submodule data-model -*/ - -})(); - - - -(function() { -/** - An AttributeChange object is created whenever a record's - attribute changes value. It is used to track changes to a - record between transaction commits. -*/ - -var AttributeChange = DS.AttributeChange = function(options) { - this.reference = options.reference; - this.store = options.store; - this.name = options.name; - this.oldValue = options.oldValue; -}; - -AttributeChange.createChange = function(options) { - return new AttributeChange(options); -}; - -AttributeChange.prototype = { - sync: function() { - this.store.recordAttributeDidChange(this.reference, this.name, this.value, this.oldValue); - - // TODO: Use this object in the commit process - this.destroy(); - }, - - /** - If the AttributeChange is destroyed (either by being rolled back - or being committed), remove it from the list of pending changes - on the record. - */ - destroy: function() { - var record = this.reference.record; - - delete record._changesToSync[this.name]; - } -}; - -})(); - - - -(function() { -var get = Ember.get, set = Ember.set; -var forEach = Ember.EnumerableUtils.forEach; - -DS.RelationshipChange = function(options) { - this.parentReference = options.parentReference; - this.childReference = options.childReference; - this.firstRecordReference = options.firstRecordReference; - this.firstRecordKind = options.firstRecordKind; - this.firstRecordName = options.firstRecordName; - this.secondRecordReference = options.secondRecordReference; - this.secondRecordKind = options.secondRecordKind; - this.secondRecordName = options.secondRecordName; - this.changeType = options.changeType; - this.store = options.store; - - this.committed = {}; -}; - -DS.RelationshipChangeAdd = function(options){ - DS.RelationshipChange.call(this, options); -}; - -DS.RelationshipChangeRemove = function(options){ - DS.RelationshipChange.call(this, options); -}; - -/** @private */ -DS.RelationshipChange.create = function(options) { - return new DS.RelationshipChange(options); -}; - -/** @private */ -DS.RelationshipChangeAdd.create = function(options) { - return new DS.RelationshipChangeAdd(options); -}; - -/** @private */ -DS.RelationshipChangeRemove.create = function(options) { - return new DS.RelationshipChangeRemove(options); -}; - -DS.OneToManyChange = {}; -DS.OneToNoneChange = {}; -DS.ManyToNoneChange = {}; -DS.OneToOneChange = {}; -DS.ManyToManyChange = {}; - -DS.RelationshipChange._createChange = function(options){ - if(options.changeType === "add"){ - return DS.RelationshipChangeAdd.create(options); - } - if(options.changeType === "remove"){ - return DS.RelationshipChangeRemove.create(options); - } -}; - - -DS.RelationshipChange.determineRelationshipType = function(recordType, knownSide){ - var knownKey = knownSide.key, key, otherKind; - var knownKind = knownSide.kind; - - var inverse = recordType.inverseFor(knownKey); - - if (inverse){ - key = inverse.name; - otherKind = inverse.kind; - } - - if (!inverse){ - return knownKind === "belongsTo" ? "oneToNone" : "manyToNone"; - } - else{ - if(otherKind === "belongsTo"){ - return knownKind === "belongsTo" ? "oneToOne" : "manyToOne"; - } - else{ - return knownKind === "belongsTo" ? "oneToMany" : "manyToMany"; - } - } - -}; - -DS.RelationshipChange.createChange = function(firstRecordReference, secondRecordReference, store, options){ - // Get the type of the child based on the child's client ID - var firstRecordType = firstRecordReference.type, changeType; - changeType = DS.RelationshipChange.determineRelationshipType(firstRecordType, options); - if (changeType === "oneToMany"){ - return DS.OneToManyChange.createChange(firstRecordReference, secondRecordReference, store, options); - } - else if (changeType === "manyToOne"){ - return DS.OneToManyChange.createChange(secondRecordReference, firstRecordReference, store, options); - } - else if (changeType === "oneToNone"){ - return DS.OneToNoneChange.createChange(firstRecordReference, secondRecordReference, store, options); - } - else if (changeType === "manyToNone"){ - return DS.ManyToNoneChange.createChange(firstRecordReference, secondRecordReference, store, options); - } - else if (changeType === "oneToOne"){ - return DS.OneToOneChange.createChange(firstRecordReference, secondRecordReference, store, options); - } - else if (changeType === "manyToMany"){ - return DS.ManyToManyChange.createChange(firstRecordReference, secondRecordReference, store, options); - } -}; - -/** @private */ -DS.OneToNoneChange.createChange = function(childReference, parentReference, store, options) { - var key = options.key; - var change = DS.RelationshipChange._createChange({ - parentReference: parentReference, - childReference: childReference, - firstRecordReference: childReference, - store: store, - changeType: options.changeType, - firstRecordName: key, - firstRecordKind: "belongsTo" - }); - - store.addRelationshipChangeFor(childReference, key, parentReference, null, change); - - return change; -}; - -/** @private */ -DS.ManyToNoneChange.createChange = function(childReference, parentReference, store, options) { - var key = options.key; - var change = DS.RelationshipChange._createChange({ - parentReference: childReference, - childReference: parentReference, - secondRecordReference: childReference, - store: store, - changeType: options.changeType, - secondRecordName: options.key, - secondRecordKind: "hasMany" - }); - - store.addRelationshipChangeFor(childReference, key, parentReference, null, change); - return change; -}; - - -/** @private */ -DS.ManyToManyChange.createChange = function(childReference, parentReference, store, options) { - // If the name of the belongsTo side of the relationship is specified, - // use that - // If the type of the parent is specified, look it up on the child's type - // definition. - var key = options.key; - - var change = DS.RelationshipChange._createChange({ - parentReference: parentReference, - childReference: childReference, - firstRecordReference: childReference, - secondRecordReference: parentReference, - firstRecordKind: "hasMany", - secondRecordKind: "hasMany", - store: store, - changeType: options.changeType, - firstRecordName: key - }); - - store.addRelationshipChangeFor(childReference, key, parentReference, null, change); - - - return change; -}; - -/** @private */ -DS.OneToOneChange.createChange = function(childReference, parentReference, store, options) { - var key; - - // If the name of the belongsTo side of the relationship is specified, - // use that - // If the type of the parent is specified, look it up on the child's type - // definition. - if (options.parentType) { - key = options.parentType.inverseFor(options.key).name; - } else if (options.key) { - key = options.key; - } else { - Ember.assert("You must pass either a parentType or belongsToName option to OneToManyChange.forChildAndParent", false); - } - - var change = DS.RelationshipChange._createChange({ - parentReference: parentReference, - childReference: childReference, - firstRecordReference: childReference, - secondRecordReference: parentReference, - firstRecordKind: "belongsTo", - secondRecordKind: "belongsTo", - store: store, - changeType: options.changeType, - firstRecordName: key - }); - - store.addRelationshipChangeFor(childReference, key, parentReference, null, change); - - - return change; -}; - -DS.OneToOneChange.maintainInvariant = function(options, store, childReference, key){ - if (options.changeType === "add" && store.recordIsMaterialized(childReference)) { - var child = store.recordForReference(childReference); - var oldParent = get(child, key); - if (oldParent){ - var correspondingChange = DS.OneToOneChange.createChange(childReference, oldParent.get('_reference'), store, { - parentType: options.parentType, - hasManyName: options.hasManyName, - changeType: "remove", - key: options.key - }); - store.addRelationshipChangeFor(childReference, key, options.parentReference , null, correspondingChange); - correspondingChange.sync(); - } - } -}; - -/** @private */ -DS.OneToManyChange.createChange = function(childReference, parentReference, store, options) { - var key; - - // If the name of the belongsTo side of the relationship is specified, - // use that - // If the type of the parent is specified, look it up on the child's type - // definition. - if (options.parentType) { - key = options.parentType.inverseFor(options.key).name; - DS.OneToManyChange.maintainInvariant( options, store, childReference, key ); - } else if (options.key) { - key = options.key; - } else { - Ember.assert("You must pass either a parentType or belongsToName option to OneToManyChange.forChildAndParent", false); - } - - var change = DS.RelationshipChange._createChange({ - parentReference: parentReference, - childReference: childReference, - firstRecordReference: childReference, - secondRecordReference: parentReference, - firstRecordKind: "belongsTo", - secondRecordKind: "hasMany", - store: store, - changeType: options.changeType, - firstRecordName: key - }); - - store.addRelationshipChangeFor(childReference, key, parentReference, change.getSecondRecordName(), change); - - - return change; -}; - - -DS.OneToManyChange.maintainInvariant = function(options, store, childReference, key){ - var child = childReference.record; - - if (options.changeType === "add" && child) { - var oldParent = get(child, key); - if (oldParent){ - var correspondingChange = DS.OneToManyChange.createChange(childReference, oldParent.get('_reference'), store, { - parentType: options.parentType, - hasManyName: options.hasManyName, - changeType: "remove", - key: options.key - }); - store.addRelationshipChangeFor(childReference, key, options.parentReference, correspondingChange.getSecondRecordName(), correspondingChange); - correspondingChange.sync(); - } - } -}; - -DS.OneToManyChange.ensureSameTransaction = function(changes){ - var records = Ember.A(); - forEach(changes, function(change){ - records.addObject(change.getSecondRecord()); - records.addObject(change.getFirstRecord()); - }); - - return DS.Transaction.ensureSameTransaction(records); -}; - -DS.RelationshipChange.prototype = { - - getSecondRecordName: function() { - var name = this.secondRecordName, parent; - - if (!name) { - parent = this.secondRecordReference; - if (!parent) { return; } - - var childType = this.firstRecordReference.type; - var inverse = childType.inverseFor(this.firstRecordName); - this.secondRecordName = inverse.name; - } - - return this.secondRecordName; - }, - - /** - Get the name of the relationship on the belongsTo side. - - @return {String} - */ - getFirstRecordName: function() { - var name = this.firstRecordName; - return name; - }, - - /** @private */ - destroy: function() { - var childReference = this.childReference, - belongsToName = this.getFirstRecordName(), - hasManyName = this.getSecondRecordName(), - store = this.store; - - store.removeRelationshipChangeFor(childReference, belongsToName, this.parentReference, hasManyName, this.changeType); - }, - - /** @private */ - getByReference: function(reference) { - var store = this.store; - - // return null or undefined if the original reference was null or undefined - if (!reference) { return reference; } - - if (reference.record) { - return reference.record; - } - }, - - getSecondRecord: function(){ - return this.getByReference(this.secondRecordReference); - }, - - /** @private */ - getFirstRecord: function() { - return this.getByReference(this.firstRecordReference); - }, - - /** - @private - - Make sure that all three parts of the relationship change are part of - the same transaction. If any of the three records is clean and in the - default transaction, and the rest are in a different transaction, move - them all into that transaction. - */ - ensureSameTransaction: function() { - var child = this.getFirstRecord(), - parentRecord = this.getSecondRecord(); - - var transaction = DS.Transaction.ensureSameTransaction([child, parentRecord]); - - this.transaction = transaction; - return transaction; - }, - - callChangeEvents: function(){ - var child = this.getFirstRecord(), - parentRecord = this.getSecondRecord(); - - var dirtySet = new Ember.OrderedSet(); - - // TODO: This implementation causes a race condition in key-value - // stores. The fix involves buffering changes that happen while - // a record is loading. A similar fix is required for other parts - // of ember-data, and should be done as new infrastructure, not - // a one-off hack. [tomhuda] - if (parentRecord && get(parentRecord, 'isLoaded')) { - this.store.recordHasManyDidChange(dirtySet, parentRecord, this); - } - - if (child) { - this.store.recordBelongsToDidChange(dirtySet, child, this); - } - - dirtySet.forEach(function(record) { - record.adapterDidDirty(); - }); - }, - - coalesce: function(){ - var relationshipPairs = this.store.relationshipChangePairsFor(this.firstRecordReference); - forEach(relationshipPairs, function(pair){ - var addedChange = pair["add"]; - var removedChange = pair["remove"]; - if(addedChange && removedChange) { - addedChange.destroy(); - removedChange.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 secondRecordName = this.getSecondRecordName(), - firstRecordName = this.getFirstRecordName(), - firstRecord = this.getFirstRecord(), - secondRecord = this.getSecondRecord(); - - //Ember.assert("You specified a hasMany (" + hasManyName + ") on " + (!belongsToName && (newParent || oldParent || this.lastParent).constructor) + " but did not specify an inverse belongsTo on " + child.constructor, belongsToName); - //Ember.assert("You specified a belongsTo (" + belongsToName + ") on " + child.constructor + " but did not specify an inverse hasMany on " + (!hasManyName && (newParent || oldParent || this.lastParentRecord).constructor), hasManyName); - - this.ensureSameTransaction(); - - this.callChangeEvents(); - - if (secondRecord && firstRecord) { - if(this.secondRecordKind === "belongsTo"){ - secondRecord.suspendRelationshipObservers(function(){ - set(secondRecord, secondRecordName, firstRecord); - }); - - } - else if(this.secondRecordKind === "hasMany"){ - secondRecord.suspendRelationshipObservers(function(){ - get(secondRecord, secondRecordName).addObject(firstRecord); - }); - } - } - - if (firstRecord && secondRecord && get(firstRecord, firstRecordName) !== secondRecord) { - if(this.firstRecordKind === "belongsTo"){ - firstRecord.suspendRelationshipObservers(function(){ - set(firstRecord, firstRecordName, secondRecord); - }); - } - else if(this.firstRecordKind === "hasMany"){ - firstRecord.suspendRelationshipObservers(function(){ - get(firstRecord, firstRecordName).addObject(secondRecord); - }); - } - } - - this.coalesce(); -}; - -DS.RelationshipChangeRemove.prototype.changeType = "remove"; -DS.RelationshipChangeRemove.prototype.sync = function() { - var secondRecordName = this.getSecondRecordName(), - firstRecordName = this.getFirstRecordName(), - firstRecord = this.getFirstRecord(), - secondRecord = this.getSecondRecord(); - - //Ember.assert("You specified a hasMany (" + hasManyName + ") on " + (!belongsToName && (newParent || oldParent || this.lastParent).constructor) + " but did not specify an inverse belongsTo on " + child.constructor, belongsToName); - //Ember.assert("You specified a belongsTo (" + belongsToName + ") on " + child.constructor + " but did not specify an inverse hasMany on " + (!hasManyName && (newParent || oldParent || this.lastParentRecord).constructor), hasManyName); - - this.ensureSameTransaction(firstRecord, secondRecord, secondRecordName, firstRecordName); - - this.callChangeEvents(); - - if (secondRecord && firstRecord) { - if(this.secondRecordKind === "belongsTo"){ - secondRecord.suspendRelationshipObservers(function(){ - set(secondRecord, secondRecordName, null); - }); - } - else if(this.secondRecordKind === "hasMany"){ - secondRecord.suspendRelationshipObservers(function(){ - get(secondRecord, secondRecordName).removeObject(firstRecord); - }); - } - } - - if (firstRecord && get(firstRecord, firstRecordName)) { - if(this.firstRecordKind === "belongsTo"){ - firstRecord.suspendRelationshipObservers(function(){ - set(firstRecord, firstRecordName, null); - }); - } - else if(this.firstRecordKind === "hasMany"){ - firstRecord.suspendRelationshipObservers(function(){ - get(firstRecord, firstRecordName).removeObject(secondRecord); - }); - } - } - - this.coalesce(); -}; - -})(); - - - -(function() { -/** - @module data - @submodule data-changes -*/ - -})(); - - - -(function() { -var get = Ember.get, set = Ember.set, - isNone = Ember.isNone; - -DS.belongsTo = function(type, options) { - Ember.assert("The first argument DS.belongsTo must be a model type or string, like DS.belongsTo(App.Person)", !!type && (typeof type === 'string' || DS.Model.detect(type))); - - options = options || {}; - - var meta = { type: type, isRelationship: true, options: options, kind: 'belongsTo' }; - - return Ember.computed(function(key, value) { - if (typeof type === 'string') { - type = get(this, type, false) || get(Ember.lookup, type); - } - - if (arguments.length === 2) { - Ember.assert("You can only add a record of " + type.toString() + " to this relationship", !value || type.detectInstance(value)); - return value === undefined ? null : value; - } - - var data = get(this, 'data').belongsTo, - store = get(this, 'store'), belongsTo; - - belongsTo = data[key]; - - // TODO (tomdale) The value of the belongsTo in the data hash can be - // one of: - // 1. null/undefined - // 2. a record reference - // 3. a tuple returned by the serializer's polymorphism code - // - // We should really normalize #3 to be the same as #2 to reduce the - // complexity here. - - if (isNone(belongsTo)) { - return null; - } - - // The data has been normalized to a record reference, so - // just ask the store for the record for that reference, - // materializing it if necessary. - if (belongsTo.clientId) { - return store.recordForReference(belongsTo); - } - - // The data has been normalized into a type/id pair by the - // serializer's polymorphism code. - return store.findById(belongsTo.type, belongsTo.id); - }).property('data').meta(meta); -}; - -/** - These observers observe all `belongsTo` relationships on the record. See - `relationships/ext` to see how these observers get their dependencies. - -*/ - -DS.Model.reopen({ - /** @private */ - belongsToWillChange: Ember.beforeObserver(function(record, key) { - if (get(record, 'isLoaded')) { - var oldParent = get(record, key); - - var childReference = get(record, '_reference'), - store = get(record, 'store'); - if (oldParent){ - var change = DS.RelationshipChange.createChange(childReference, get(oldParent, '_reference'), store, { key: key, kind:"belongsTo", changeType: "remove" }); - change.sync(); - this._changesToSync[key] = change; - } - } - }), - - /** @private */ - belongsToDidChange: Ember.immediateObserver(function(record, key) { - if (get(record, 'isLoaded')) { - var newParent = get(record, key); - if(newParent){ - var childReference = get(record, '_reference'), - store = get(record, 'store'); - var change = DS.RelationshipChange.createChange(childReference, get(newParent, '_reference'), store, { key: key, kind:"belongsTo", changeType: "add" }); - change.sync(); - if(this._changesToSync[key]){ - DS.OneToManyChange.ensureSameTransaction([change, this._changesToSync[key]], store); - } - } - } - delete this._changesToSync[key]; - }) -}); - -})(); - - - -(function() { -var get = Ember.get, set = Ember.set, forEach = Ember.EnumerableUtils.forEach; -var hasRelationship = function(type, options) { - options = options || {}; - - var meta = { type: type, isRelationship: true, options: options, kind: 'hasMany' }; - - return Ember.computed(function(key, value) { - var data = get(this, 'data').hasMany, - store = get(this, 'store'), - ids, relationship; - - if (typeof type === 'string') { - type = get(this, type, false) || get(Ember.lookup, type); - } - - //ids can be references or opaque token - //(e.g. `{url: '/relationship'}`) that will be passed to the adapter - ids = data[key]; - - relationship = store.findMany(type, ids, this, meta); - set(relationship, 'owner', this); - set(relationship, 'name', key); - set(relationship, 'isPolymorphic', options.polymorphic); - - return relationship; - }).property().meta(meta); -}; - -DS.hasMany = function(type, options) { - Ember.assert("The type passed to DS.hasMany must be defined", !!type); - return hasRelationship(type, options); -}; - -function clearUnmaterializedHasMany(record, relationship) { - var store = get(record, 'store'), - data = get(record, 'data').hasMany; - - var references = data[relationship.key]; - - if (!references) { return; } - - var inverse = record.constructor.inverseFor(relationship.key); - - if (inverse) { - forEach(references, function(reference) { - var childRecord; - - if (childRecord = reference.record) { - record.suspendRelationshipObservers(function() { - set(childRecord, inverse.name, null); - }); - } - }); - } -} - -DS.Model.reopen({ - clearHasMany: function(relationship) { - var hasMany = this.cacheFor(relationship.name); - - if (hasMany) { - hasMany.clear(); - } else { - clearUnmaterializedHasMany(this, relationship); - } - } -}); - -})(); - - - -(function() { -var get = Ember.get, set = Ember.set; - -/** - @private - - This file defines several extensions to the base `DS.Model` class that - add support for one-to-many relationships. -*/ - -DS.Model.reopen({ - // This Ember.js hook allows an object to be notified when a property - // is defined. - // - // In this case, we use it to be notified when an Ember Data user defines a - // belongs-to relationship. In that case, we need to set up observers for - // each one, allowing us to track relationship changes and automatically - // reflect changes in the inverse has-many array. - // - // This hook passes the class being set up, as well as the key and value - // being defined. So, for example, when the user does this: - // - // DS.Model.extend({ - // parent: DS.belongsTo(App.User) - // }); - // - // This hook would be called with "parent" as the key and the computed - // property returned by `DS.belongsTo` as the value. - didDefineProperty: function(proto, key, value) { - // Check if the value being set is a computed property. - if (value instanceof Ember.Descriptor) { - - // If it is, get the metadata for the relationship. This is - // populated by the `DS.belongsTo` helper when it is creating - // the computed property. - var meta = value.meta(); - - if (meta.isRelationship && meta.kind === 'belongsTo') { - Ember.addObserver(proto, key, null, 'belongsToDidChange'); - Ember.addBeforeObserver(proto, key, null, 'belongsToWillChange'); - } - - if (meta.isAttribute) { - Ember.addObserver(proto, key, null, 'attributeDidChange'); - Ember.addBeforeObserver(proto, key, null, 'attributeWillChange'); - } - - meta.parentType = proto.constructor; - } - } -}); - -/** - These DS.Model extensions add class methods that provide relationship - introspection abilities about relationships. - - A note about the computed properties contained here: - - **These properties are effectively sealed once called for the first time.** - To avoid repeatedly doing expensive iteration over a model's fields, these - values are computed once and then cached for the remainder of the runtime of - your application. - - If your application needs to modify a class after its initial definition - (for example, using `reopen()` to add additional attributes), make sure you - do it before using your model with the store, which uses these properties - extensively. -*/ - -DS.Model.reopenClass({ - /** - For a given relationship name, returns the model type of the relationship. - - For example, if you define a model like this: - - App.Post = DS.Model.extend({ - comments: DS.hasMany(App.Comment) - }); - - Calling `App.Post.typeForRelationship('comments')` will return `App.Comment`. - - @param {String} name the name of the relationship - @return {subclass of DS.Model} the type of the relationship, or undefined - */ - typeForRelationship: function(name) { - var relationship = get(this, 'relationshipsByName').get(name); - return relationship && relationship.type; - }, - - inverseFor: function(name) { - var inverseType = this.typeForRelationship(name); - - if (!inverseType) { return null; } - - var options = this.metaForProperty(name).options; - var inverseName, inverseKind; - - if (options.inverse) { - inverseName = options.inverse; - inverseKind = Ember.get(inverseType, 'relationshipsByName').get(inverseName).kind; - } else { - var possibleRelationships = findPossibleInverses(this, inverseType); - - if (possibleRelationships.length === 0) { return null; } - - Ember.assert("You defined the '" + name + "' relationship on " + this + ", but multiple possible inverse relationships of type " + this + " were found on " + inverseType + ".", possibleRelationships.length === 1); - - inverseName = possibleRelationships[0].name; - inverseKind = possibleRelationships[0].kind; - } - - function findPossibleInverses(type, inverseType, possibleRelationships) { - possibleRelationships = possibleRelationships || []; - - var relationshipMap = get(inverseType, 'relationships'); - if (!relationshipMap) { return; } - - var relationships = relationshipMap.get(type); - if (relationships) { - possibleRelationships.push.apply(possibleRelationships, relationshipMap.get(type)); - } - - if (type.superclass) { - findPossibleInverses(type.superclass, inverseType, possibleRelationships); - } - - return possibleRelationships; - } - - return { - type: inverseType, - name: inverseName, - kind: inverseKind - }; - }, - - /** - The model's relationships as a map, keyed on the type of the - relationship. The value of each entry is an array containing a descriptor - for each relationship with that type, describing the name of the relationship - as well as the type. - - For example, given the following model definition: - - App.Blog = DS.Model.extend({ - users: DS.hasMany(App.User), - owner: DS.belongsTo(App.User), - posts: DS.hasMany(App.Post) - }); - - This computed property would return a map describing these - relationships, like this: - - var relationships = Ember.get(App.Blog, 'relationships'); - relationships.get(App.User); - //=> [ { name: 'users', kind: 'hasMany' }, - // { name: 'owner', kind: 'belongsTo' } ] - relationships.get(App.Post); - //=> [ { name: 'posts', kind: 'hasMany' } ] - - @type Ember.Map - @readOnly - */ - relationships: Ember.computed(function() { - var map = new Ember.MapWithDefault({ - defaultValue: function() { return []; } - }); - - // Loop through each computed property on the class - this.eachComputedProperty(function(name, meta) { - - // If the computed property is a relationship, add - // it to the map. - if (meta.isRelationship) { - if (typeof meta.type === 'string') { - meta.type = Ember.get(Ember.lookup, meta.type); - } - - var relationshipsForType = map.get(meta.type); - - relationshipsForType.push({ name: name, kind: meta.kind }); - } - }); - - return map; - }), - - /** - A hash containing lists of the model's relationships, grouped - by the relationship kind. For example, given a model with this - definition: - - App.Blog = DS.Model.extend({ - users: DS.hasMany(App.User), - owner: DS.belongsTo(App.User), - - posts: DS.hasMany(App.Post) - }); - - This property would contain the following: - - var relationshipNames = Ember.get(App.Blog, 'relationshipNames'); - relationshipNames.hasMany; - //=> ['users', 'posts'] - relationshipNames.belongsTo; - //=> ['owner'] - - @type Object - @readOnly - */ - relationshipNames: Ember.computed(function() { - var names = { hasMany: [], belongsTo: [] }; - - this.eachComputedProperty(function(name, meta) { - if (meta.isRelationship) { - names[meta.kind].push(name); - } - }); - - return names; - }), - - /** - An array of types directly related to a model. Each type will be - included once, regardless of the number of relationships it has with - the model. - - For example, given a model with this definition: - - App.Blog = DS.Model.extend({ - users: DS.hasMany(App.User), - owner: DS.belongsTo(App.User), - posts: DS.hasMany(App.Post) - }); - - This property would contain the following: - - var relatedTypes = Ember.get(App.Blog, 'relatedTypes'); - //=> [ App.User, App.Post ] - - @type Ember.Array - @readOnly - */ - relatedTypes: Ember.computed(function() { - var type, - types = Ember.A([]); - - // Loop through each computed property on the class, - // and create an array of the unique types involved - // in relationships - this.eachComputedProperty(function(name, meta) { - if (meta.isRelationship) { - type = meta.type; - - if (typeof type === 'string') { - type = get(this, type, false) || get(Ember.lookup, type); - } - - Ember.assert("You specified a hasMany (" + meta.type + ") on " + meta.parentType + " but " + meta.type + " was not found.", type); - - if (!types.contains(type)) { - Ember.assert("Trying to sideload " + name + " on " + this.toString() + " but the type doesn't exist.", !!type); - types.push(type); - } - } - }); - - return types; - }), - - /** - A map whose keys are the relationships of a model and whose values are - relationship descriptors. - - For example, given a model with this - definition: - - App.Blog = DS.Model.extend({ - users: DS.hasMany(App.User), - owner: DS.belongsTo(App.User), - - posts: DS.hasMany(App.Post) - }); - - This property would contain the following: - - var relationshipsByName = Ember.get(App.Blog, 'relationshipsByName'); - relationshipsByName.get('users'); - //=> { key: 'users', kind: 'hasMany', type: App.User } - relationshipsByName.get('owner'); - //=> { key: 'owner', kind: 'belongsTo', type: App.User } - - @type Ember.Map - @readOnly - */ - relationshipsByName: Ember.computed(function() { - var map = Ember.Map.create(), type; - - this.eachComputedProperty(function(name, meta) { - if (meta.isRelationship) { - meta.key = name; - type = meta.type; - - if (typeof type === 'string') { - type = get(this, type, false) || get(Ember.lookup, type); - meta.type = type; - } - - map.set(name, meta); - } - }); - - return map; - }), - - /** - A map whose keys are the fields of the model and whose values are strings - describing the kind of the field. A model's fields are the union of all of its - attributes and relationships. - - For example: - - App.Blog = DS.Model.extend({ - users: DS.hasMany(App.User), - owner: DS.belongsTo(App.User), - - posts: DS.hasMany(App.Post), - - title: DS.attr('string') - }); - - var fields = Ember.get(App.Blog, 'fields'); - fields.forEach(function(field, kind) { - console.log(field, kind); - }); - - // prints: - // users, hasMany - // owner, belongsTo - // posts, hasMany - // title, attribute - - @type Ember.Map - @readOnly - */ - fields: Ember.computed(function() { - var map = Ember.Map.create(); - - this.eachComputedProperty(function(name, meta) { - if (meta.isRelationship) { - map.set(name, meta.kind); - } else if (meta.isAttribute) { - map.set(name, 'attribute'); - } - }); - - return map; - }), - - /** - Given a callback, iterates over each of the relationships in the model, - invoking the callback with the name of each relationship and its relationship - descriptor. - - @param {Function} callback the callback to invoke - @param {any} binding the value to which the callback's `this` should be bound - */ - eachRelationship: function(callback, binding) { - get(this, 'relationshipsByName').forEach(function(name, relationship) { - callback.call(binding, name, relationship); - }); - }, - - /** - Given a callback, iterates over each of the types related to a model, - invoking the callback with the related type's class. Each type will be - returned just once, regardless of how many different relationships it has - with a model. - - @param {Function} callback the callback to invoke - @param {any} binding the value to which the callback's `this` should be bound - */ - eachRelatedType: function(callback, binding) { - get(this, 'relatedTypes').forEach(function(type) { - callback.call(binding, type); - }); - } -}); - -DS.Model.reopen({ - /** - Given a callback, iterates over each of the relationships in the model, - invoking the callback with the name of each relationship and its relationship - descriptor. - - @param {Function} callback the callback to invoke - @param {any} binding the value to which the callback's `this` should be bound - */ - eachRelationship: function(callback, binding) { - this.constructor.eachRelationship(callback, binding); - } -}); - -})(); - - - -(function() { -/** - @module data - @submodule data-relationships -*/ - -})(); - - - -(function() { -var get = Ember.get, set = Ember.set; -var once = Ember.run.once; -var forEach = Ember.EnumerableUtils.forEach; - -DS.RecordArrayManager = Ember.Object.extend({ - init: function() { - this.filteredRecordArrays = Ember.MapWithDefault.create({ - defaultValue: function() { return []; } - }); - - this.changedReferences = []; - }, - - referenceDidChange: function(reference) { - this.changedReferences.push(reference); - once(this, this.updateRecordArrays); - }, - - recordArraysForReference: function(reference) { - reference.recordArrays = reference.recordArrays || Ember.OrderedSet.create(); - return reference.recordArrays; - }, - - /** - @private - - This method is invoked whenever data is loaded into the store - by the adapter or updated by the adapter, or when an attribute - changes on a record. - - It updates all filters that a record belongs to. - - To avoid thrashing, it only runs once per run loop per record. - - @param {Class} type - @param {Number|String} clientId - */ - updateRecordArrays: function() { - forEach(this.changedReferences, function(reference) { - var type = reference.type, - recordArrays = this.filteredRecordArrays.get(type), - filter; - - forEach(recordArrays, function(array) { - filter = get(array, 'filterFunction'); - this.updateRecordArray(array, filter, type, reference); - }, this); - - // loop through all manyArrays containing an unloaded copy of this - // clientId and notify them that the record was loaded. - var manyArrays = reference.loadingRecordArrays; - - if (manyArrays) { - for (var i=0, l=manyArrays.length; i blog_post) - // 2. Extract the part after `blog_post_` (`blog_comments`) - // 3. Underscore it, to become `blogComments` - var typeString = type.toString().split(".")[1].underscore(); - return name.match(new RegExp("^" + typeString + "_(.*)$"))[1].camelize(); - } - }); - ``` - - @method keyForHasMany - @param {DS.Model subclass} type the type of the record with - the `belongsTo` relationship. - @param {String} name the relationship name to convert into a key - - @returns {String} the key - */ - keyForHasMany: function(type, name) { - return this.keyForAttributeName(type, name); - }, - - //......................... - //. MATERIALIZATION HOOKS - //......................... - - materialize: function(record, serialized, prematerialized) { - var id; - if (Ember.isNone(get(record, 'id'))) { - if (prematerialized && prematerialized.hasOwnProperty('id')) { - id = prematerialized.id; - } else { - id = this.extractId(record.constructor, serialized); - } - record.materializeId(id); - } - - this.materializeAttributes(record, serialized, prematerialized); - this.materializeRelationships(record, serialized, prematerialized); - }, - - deserializeValue: function(value, attributeType) { - var transform = this.transforms ? this.transforms[attributeType] : null; - - Ember.assert("You tried to use a attribute type (" + attributeType + ") that has not been registered", transform); - return transform.deserialize(value); - }, - - materializeAttributes: function(record, serialized, prematerialized) { - record.eachAttribute(function(name, attribute) { - if (prematerialized && prematerialized.hasOwnProperty(name)) { - record.materializeAttribute(name, prematerialized[name]); - } else { - this.materializeAttribute(record, serialized, name, attribute.type); - } - }, this); - }, - - materializeAttribute: function(record, serialized, attributeName, attributeType) { - var value = this.extractAttribute(record.constructor, serialized, attributeName); - value = this.deserializeValue(value, attributeType); - - record.materializeAttribute(attributeName, value); - }, - - materializeRelationships: function(record, hash, prematerialized) { - record.eachRelationship(function(name, relationship) { - if (relationship.kind === 'hasMany') { - if (prematerialized && prematerialized.hasOwnProperty(name)) { - var tuplesOrReferencesOrOpaque = this._convertPrematerializedHasMany(relationship.type, prematerialized[name]); - record.materializeHasMany(name, tuplesOrReferencesOrOpaque); - } else { - this.materializeHasMany(name, record, hash, relationship, prematerialized); - } - } else if (relationship.kind === 'belongsTo') { - if (prematerialized && prematerialized.hasOwnProperty(name)) { - var tupleOrReference = this._convertTuple(relationship.type, prematerialized[name]); - record.materializeBelongsTo(name, tupleOrReference); - } else { - this.materializeBelongsTo(name, record, hash, relationship, prematerialized); - } - } - }, this); - }, - - materializeHasMany: function(name, record, hash, relationship) { - var type = record.constructor, - key = this._keyForHasMany(type, relationship.key), - idsOrTuples = this.extractHasMany(type, hash, key), - tuples = idsOrTuples; - - if(idsOrTuples && Ember.isArray(idsOrTuples)) { - tuples = this._convertTuples(relationship.type, idsOrTuples); - } - - record.materializeHasMany(name, tuples); - }, - - materializeBelongsTo: function(name, record, hash, relationship) { - var type = record.constructor, - key = this._keyForBelongsTo(type, relationship.key), - idOrTuple, - tuple = null; - - if(relationship.options && relationship.options.polymorphic) { - idOrTuple = this.extractBelongsToPolymorphic(type, hash, key); - } else { - idOrTuple = this.extractBelongsTo(type, hash, key); - } - - if(!isNone(idOrTuple)) { - tuple = this._convertTuple(relationship.type, idOrTuple); - } - - record.materializeBelongsTo(name, tuple); - }, - - _convertPrematerializedHasMany: function(type, prematerializedHasMany) { - var tuplesOrReferencesOrOpaque; - if( typeof prematerializedHasMany === 'string' ) { - tuplesOrReferencesOrOpaque = prematerializedHasMany; - } else { - tuplesOrReferencesOrOpaque = this._convertTuples(type, prematerializedHasMany); - } - return tuplesOrReferencesOrOpaque; - }, - - _convertTuples: function(type, idsOrTuples) { - return map.call(idsOrTuples, function(idOrTuple) { - return this._convertTuple(type, idOrTuple); - }, this); - }, - - _convertTuple: function(type, idOrTuple) { - var foundType; - - if (typeof idOrTuple === 'object') { - if (DS.Model.detect(idOrTuple.type)) { - return idOrTuple; - } else { - foundType = this.typeFromAlias(idOrTuple.type); - Ember.assert("Unable to resolve type " + idOrTuple.type + ". You may need to configure your serializer aliases.", !!foundType); - - return {id: idOrTuple.id, type: foundType}; - } - } - return {id: idOrTuple, type: type}; - }, - - /** - @private - - This method is called to get the primary key for a given - type. - - If a primary key configuration exists for this type, this - method will return the configured value. Otherwise, it will - call the public `primaryKey` hook. - - @method _primaryKey - @param {DS.Model subclass} type - @returns {String} the primary key for the type - */ - _primaryKey: function(type) { - var config = this.configurationForType(type), - primaryKey = config && config.primaryKey; - - if (primaryKey) { - return primaryKey; - } else { - return this.primaryKey(type); - } - }, - - /** - @private - - This method looks up the key for the attribute name and transforms the - attribute's value using registered transforms. - - Specifically: - - 1. Look up the key for the attribute name. If available, this will use - any registered mappings. Otherwise, it will invoke the public - `keyForAttributeName` hook. - 2. Get the value from the record using the `attributeName`. - 3. Transform the value using registered transforms for the `attributeType`. - 4. Invoke the public `addAttribute` hook with the hash, key, and - transformed value. - - @method _addAttribute - @param {any} data the serialized representation being built - @param {DS.Model} record the record to serialize - @param {String} attributeName the name of the attribute on the record - @param {String} attributeType the type of the attribute (e.g. `string` - or `boolean`) - */ - _addAttribute: function(data, record, attributeName, attributeType) { - var key = this._keyForAttributeName(record.constructor, attributeName); - var value = get(record, attributeName); - - this.addAttribute(data, key, this.serializeValue(value, attributeType)); - }, - - /** - @private - - This method looks up the primary key for the `type` and invokes - `serializeId` on the `id`. - - It then invokes the public `addId` hook with the primary key and - the serialized id. - - @method _addId - @param {any} data the serialized representation that is being built - @param {Ember.Model subclass} type - @param {any} id the materialized id from the record - */ - _addId: function(hash, type, id) { - var primaryKey = this._primaryKey(type); - - this.addId(hash, primaryKey, this.serializeId(id)); - }, - - /** - @private - - This method is called to get a key used in the data from - an attribute name. It first checks for any mappings before - calling the public hook `keyForAttributeName`. - - @method _keyForAttributeName - @param {DS.Model subclass} type the type of the record with - the attribute name `name` - @param {String} name the attribute name to convert into a key - - @returns {String} the key - */ - _keyForAttributeName: function(type, name) { - return this._keyFromMappingOrHook('keyForAttributeName', type, name); - }, - - /** - @private - - This method is called to get a key used in the data from - a belongsTo relationship. It first checks for any mappings before - calling the public hook `keyForBelongsTo`. - - @method _keyForBelongsTo - @param {DS.Model subclass} type the type of the record with - the `belongsTo` relationship. - @param {String} name the relationship name to convert into a key - - @returns {String} the key - */ - _keyForBelongsTo: function(type, name) { - return this._keyFromMappingOrHook('keyForBelongsTo', type, name); - }, - - keyFor: function(description) { - var type = description.parentType, - name = description.key; - - switch (description.kind) { - case 'belongsTo': - return this._keyForBelongsTo(type, name); - case 'hasMany': - return this._keyForHasMany(type, name); - } - }, - - /** - @private - - This method is called to get a key used in the data from - a hasMany relationship. It first checks for any mappings before - calling the public hook `keyForHasMany`. - - @method _keyForHasMany - @param {DS.Model subclass} type the type of the record with - the `hasMany` relationship. - @param {String} name the relationship name to convert into a key - - @returns {String} the key - */ - _keyForHasMany: function(type, name) { - return this._keyFromMappingOrHook('keyForHasMany', type, name); - }, - /** - @private - - This method converts the relationship name to a key for serialization, - and then invokes the public `addBelongsTo` hook. - - @method _addBelongsTo - @param {any} data the serialized representation that is being built - @param {DS.Model} record the record to serialize - @param {String} name the relationship name - @param {Object} relationship an object representing the relationship - */ - _addBelongsTo: function(data, record, name, relationship) { - var key = this._keyForBelongsTo(record.constructor, name); - this.addBelongsTo(data, record, key, relationship); - }, - - /** - @private - - This method converts the relationship name to a key for serialization, - and then invokes the public `addHasMany` hook. - - @method _addHasMany - @param {any} data the serialized representation that is being built - @param {DS.Model} record the record to serialize - @param {String} name the relationship name - @param {Object} relationship an object representing the relationship - */ - _addHasMany: function(data, record, name, relationship) { - var key = this._keyForHasMany(record.constructor, name); - this.addHasMany(data, record, key, relationship); - }, - - /** - @private - - An internal method that handles checking whether a mapping - exists for a particular attribute or relationship name before - calling the public hooks. - - If a mapping is found, and the mapping has a key defined, - use that instead of invoking the hook. - - @method _keyFromMappingOrHook - @param {String} publicMethod the public hook to invoke if - a mapping is not found (e.g. `keyForAttributeName`) - @param {DS.Model subclass} type the type of the record with - the attribute or relationship name. - @param {String} name the attribute or relationship name to - convert into a key - */ - _keyFromMappingOrHook: function(publicMethod, type, name) { - var key = this.mappingOption(type, name, 'key'); - - if (key) { - return key; - } else { - return this[publicMethod](type, name); - } - }, - - /** - TRANSFORMS - */ - - registerTransform: function(type, transform) { - this.transforms[type] = transform; - }, - - registerEnumTransform: function(type, objects) { - var transform = { - deserialize: function(serialized) { - return Ember.A(objects).objectAt(serialized); - }, - serialize: function(deserialized) { - return Ember.EnumerableUtils.indexOf(objects, deserialized); - }, - values: objects - }; - this.registerTransform(type, transform); - }, - - /** - MAPPING CONVENIENCE - */ - - map: function(type, mappings) { - this.mappings.set(type, mappings); - }, - - configure: function(type, configuration) { - if (type && !configuration) { - Ember.merge(this.globalConfigurations, type); - return; - } - - var config, alias; - - if (configuration.alias) { - alias = configuration.alias; - this.aliases.set(alias, type); - delete configuration.alias; - } - - config = Ember.create(this.globalConfigurations); - Ember.merge(config, configuration); - - this.configurations.set(type, config); - }, - - typeFromAlias: function(alias) { - this._completeAliases(); - return this.aliases.get(alias); - }, - - mappingForType: function(type) { - this._reifyMappings(); - return this.mappings.get(type) || {}; - }, - - configurationForType: function(type) { - this._reifyConfigurations(); - return this.configurations.get(type) || this.globalConfigurations; - }, - - _completeAliases: function() { - this._pluralizeAliases(); - this._reifyAliases(); - }, - - _pluralizeAliases: function() { - if (this._didPluralizeAliases) { return; } - - var aliases = this.aliases, - sideloadMapping = this.aliases.sideloadMapping, - plural, - self = this; - - aliases.forEach(function(key, type) { - plural = self.pluralize(key); - Ember.assert("The '" + key + "' alias has already been defined", !aliases.get(plural)); - aliases.set(plural, type); - }); - - // This map is only for backward compatibility with the `sideloadAs` option. - if (sideloadMapping) { - sideloadMapping.forEach(function(key, type) { - Ember.assert("The '" + key + "' alias has already been defined", !aliases.get(key) || (aliases.get(key)===type) ); - aliases.set(key, type); - }); - delete this.aliases.sideloadMapping; - } - - this._didPluralizeAliases = true; - }, - - _reifyAliases: function() { - if (this._didReifyAliases) { return; } - - var aliases = this.aliases, - reifiedAliases = Ember.Map.create(), - foundType; - - aliases.forEach(function(key, type) { - if (typeof type === 'string') { - foundType = Ember.get(Ember.lookup, type); - Ember.assert("Could not find model at path " + key, type); - - reifiedAliases.set(key, foundType); - } else { - reifiedAliases.set(key, type); - } - }); - - this.aliases = reifiedAliases; - this._didReifyAliases = true; - }, - - _reifyMappings: function() { - if (this._didReifyMappings) { return; } - - var mappings = this.mappings, - reifiedMappings = Ember.Map.create(); - - mappings.forEach(function(key, mapping) { - if (typeof key === 'string') { - var type = Ember.get(Ember.lookup, key); - Ember.assert("Could not find model at path " + key, type); - - reifiedMappings.set(type, mapping); - } else { - reifiedMappings.set(key, mapping); - } - }); - - this.mappings = reifiedMappings; - - this._didReifyMappings = true; - }, - - _reifyConfigurations: function() { - if (this._didReifyConfigurations) { return; } - - var configurations = this.configurations, - reifiedConfigurations = Ember.Map.create(); - - configurations.forEach(function(key, mapping) { - if (typeof key === 'string' && key !== 'plurals') { - var type = Ember.get(Ember.lookup, key); - Ember.assert("Could not find model at path " + key, type); - - reifiedConfigurations.set(type, mapping); - } else { - reifiedConfigurations.set(key, mapping); - } - }); - - this.configurations = reifiedConfigurations; - - this._didReifyConfigurations = true; - }, - - mappingOption: function(type, name, option) { - var mapping = this.mappingForType(type)[name]; - - return mapping && mapping[option]; - }, - - configOption: function(type, option) { - var config = this.configurationForType(type); - - return config[option]; - }, - - // EMBEDDED HELPERS - - embeddedType: function(type, name) { - return this.mappingOption(type, name, 'embedded'); - }, - - eachEmbeddedRecord: function(record, callback, binding) { - this.eachEmbeddedBelongsToRecord(record, callback, binding); - this.eachEmbeddedHasManyRecord(record, callback, binding); - }, - - eachEmbeddedBelongsToRecord: function(record, callback, binding) { - this.eachEmbeddedBelongsTo(record.constructor, function(name, relationship, embeddedType) { - var embeddedRecord = get(record, name); - if (embeddedRecord) { callback.call(binding, embeddedRecord, embeddedType); } - }); - }, - - eachEmbeddedHasManyRecord: function(record, callback, binding) { - this.eachEmbeddedHasMany(record.constructor, function(name, relationship, embeddedType) { - var array = get(record, name); - for (var i=0, l=get(array, 'length'); i 'low' - Server Response / Load: { myTask: {priority: 0} } - - @method registerEnumTransform - @param {String} type of the transform - @param {Array} array of String objects to use for the enumerated values. - This is an ordered list and the index values will be used for the transform. - */ - registerEnumTransform: function(attributeType, objects) { - get(this, 'serializer').registerEnumTransform(attributeType, objects); - }, - - /** - If the globally unique IDs for your records should be generated on the client, - implement the `generateIdForRecord()` method. This method will be invoked - each time you create a new record, and the value returned from it will be - assigned to the record's `primaryKey`. - - Most traditional REST-like HTTP APIs will not use this method. Instead, the ID - of the record will be set by the server, and your adapter will update the store - with the new ID when it calls `didCreateRecord()`. Only implement this method if - you intend to generate record IDs on the client-side. - - The `generateIdForRecord()` method will be invoked with the requesting store as - the first parameter and the newly created record as the second parameter: - - generateIdForRecord: function(store, record) { - var uuid = App.generateUUIDWithStatisticallyLowOddsOfCollision(); - return uuid; - } - - @method generateIdForRecord - @param {DS.Store} store - @param {DS.Model} record - */ - generateIdForRecord: null, - - materialize: function(record, data, prematerialized) { - get(this, 'serializer').materialize(record, data, prematerialized); - }, - - serialize: function(record, options) { - return get(this, 'serializer').serialize(record, options); - }, - - extractId: function(type, data) { - return get(this, 'serializer').extractId(type, data); - }, - - groupByType: function(enumerable) { - var map = Ember.MapWithDefault.create({ - defaultValue: function() { return Ember.OrderedSet.create(); } - }); - - enumerable.forEach(function(item) { - map.get(item.constructor).add(item); - }); - - return map; - }, - - commit: function(store, commitDetails) { - this.save(store, commitDetails); - }, - - save: function(store, commitDetails) { - var adapter = this; - - function filter(records) { - var filteredSet = Ember.OrderedSet.create(); - - records.forEach(function(record) { - if (adapter.shouldSave(record)) { - filteredSet.add(record); - } - }); - - return filteredSet; - } - - this.groupByType(commitDetails.created).forEach(function(type, set) { - this.createRecords(store, type, filter(set)); - }, this); - - this.groupByType(commitDetails.updated).forEach(function(type, set) { - this.updateRecords(store, type, filter(set)); - }, this); - - this.groupByType(commitDetails.deleted).forEach(function(type, set) { - this.deleteRecords(store, type, filter(set)); - }, this); - }, - - shouldSave: Ember.K, - - createRecords: function(store, type, records) { - records.forEach(function(record) { - this.createRecord(store, type, record); - }, this); - }, - - updateRecords: function(store, type, records) { - records.forEach(function(record) { - this.updateRecord(store, type, record); - }, this); - }, - - deleteRecords: function(store, type, records) { - records.forEach(function(record) { - this.deleteRecord(store, type, record); - }, this); - }, - - findMany: function(store, type, ids) { - ids.forEach(function(id) { - this.find(store, type, id); - }, this); - } -}); - -DS.Adapter.reopenClass({ - registerTransform: function(attributeType, transform) { - var registeredTransforms = this._registeredTransforms || {}; - - registeredTransforms[attributeType] = transform; - - this._registeredTransforms = registeredTransforms; - }, - - registerEnumTransform: function(attributeType, objects) { - var registeredEnumTransforms = this._registeredEnumTransforms || {}; - - registeredEnumTransforms[attributeType] = objects; - - this._registeredEnumTransforms = registeredEnumTransforms; - }, - - map: DS._Mappable.generateMapFunctionFor('attributes', function(key, newValue, map) { - var existingValue = map.get(key); - - merge(existingValue, newValue); - }), - - configure: DS._Mappable.generateMapFunctionFor('configurations', function(key, newValue, map) { - var existingValue = map.get(key); - - // If a mapping configuration is provided, peel it off and apply it - // using the DS.Adapter.map API. - var mappings = newValue && newValue.mappings; - if (mappings) { - this.map(key, mappings); - delete newValue.mappings; - } - - merge(existingValue, newValue); - }), - - resolveMapConflict: function(oldValue, newValue) { - merge(newValue, oldValue); - - return newValue; - } -}); - -})(); - - - -(function() { -/** - @module data - @submodule data-serializers -*/ - -/** - @class FixtureSerializer - @constructor - @namespace DS - @extends DS.Serializer -*/ - -var get = Ember.get, set = Ember.set; - -DS.FixtureSerializer = DS.Serializer.extend({ - deserializeValue: function(value, attributeType) { - return value; - }, - - serializeValue: function(value, attributeType) { - return value; - }, - - addId: function(data, key, id) { - data[key] = id; - }, - - addAttribute: function(hash, key, value) { - hash[key] = value; - }, - - addBelongsTo: function(hash, record, key, relationship) { - var id = get(record, relationship.key+'.id'); - if (!Ember.isNone(id)) { hash[key] = id; } - }, - - addHasMany: function(hash, record, key, relationship) { - var ids = get(record, relationship.key).map(function(item) { - return item.get('id'); - }); - - hash[relationship.key] = ids; - }, - - extract: function(loader, fixture, type, record) { - if (record) { loader.updateId(record, fixture); } - this.extractRecordRepresentation(loader, type, fixture); - }, - - extractMany: function(loader, fixtures, type, records) { - var objects = fixtures, references = []; - if (records) { records = records.toArray(); } - - for (var i = 0; i < objects.length; i++) { - if (records) { loader.updateId(records[i], objects[i]); } - var reference = this.extractRecordRepresentation(loader, type, objects[i]); - references.push(reference); - } - - loader.populateArray(references); - }, - - extractId: function(type, hash) { - var primaryKey = this._primaryKey(type); - - if (hash.hasOwnProperty(primaryKey)) { - // Ensure that we coerce IDs to strings so that record - // IDs remain consistent between application runs; especially - // if the ID is serialized and later deserialized from the URL, - // when type information will have been lost. - return hash[primaryKey]+''; - } else { - return null; - } - }, - - extractAttribute: function(type, hash, attributeName) { - var key = this._keyForAttributeName(type, attributeName); - return hash[key]; - }, - - extractHasMany: function(type, hash, key) { - return hash[key]; - }, - - extractBelongsTo: function(type, hash, key) { - var val = hash[key]; - if (val != null) { - val = val + ''; - } - return val; - }, - - extractBelongsToPolymorphic: function(type, hash, key) { - var keyForId = this.keyForPolymorphicId(key), - keyForType, - id = hash[keyForId]; - - if (id) { - keyForType = this.keyForPolymorphicType(key); - return {id: id, type: hash[keyForType]}; - } - - return null; - }, - - keyForPolymorphicId: function(key) { - return key; - }, - - keyForPolymorphicType: function(key) { - return key + '_type'; - } -}); - -})(); - - - -(function() { -/** - @module data - @submodule data-adapters -*/ - -var get = Ember.get, fmt = Ember.String.fmt, - dump = Ember.get(window, 'JSON.stringify') || function(object) { return object.toString(); }; - -/** - `DS.FixtureAdapter` is an adapter that loads records from memory. - Its primarily used for development and testing. You can also use - `DS.FixtureAdapter` while working on the API but are not ready to - integrate yet. It is a fully functioning adapter. All CRUD methods - are implemented. You can also implement query logic that a remote - system would do. Its possible to do develop your entire application - with `DS.FixtureAdapter`. - - @class FixtureAdapter - @constructor - @namespace DS - @extends DS.Adapter -*/ -DS.FixtureAdapter = DS.Adapter.extend({ - - simulateRemoteResponse: true, - - latency: 50, - - serializer: DS.FixtureSerializer, - - /* - Implement this method in order to provide data associated with a type - */ - fixturesForType: function(type) { - if (type.FIXTURES) { - var fixtures = Ember.A(type.FIXTURES); - return fixtures.map(function(fixture){ - var fixtureIdType = typeof fixture.id; - if(fixtureIdType !== "number" && fixtureIdType !== "string"){ - throw new Error(fmt('the id property must be defined as a number or string for fixture %@', [dump(fixture)])); - } - fixture.id = fixture.id + ''; - return fixture; - }); - } - return null; - }, - - /* - Implement this method in order to query fixtures data - */ - queryFixtures: function(fixtures, query, type) { - Ember.assert('Not implemented: You must override the DS.FixtureAdapter::queryFixtures method to support querying the fixture store.'); - }, - - updateFixtures: function(type, fixture) { - if(!type.FIXTURES) { - type.FIXTURES = []; - } - - var fixtures = type.FIXTURES; - - this.deleteLoadedFixture(type, fixture); - - fixtures.push(fixture); - }, - - /* - Implement this method in order to provide provide json for CRUD methods - */ - mockJSON: function(type, record) { - return this.serialize(record, { includeId: true }); - }, - - /* - Adapter methods - */ - generateIdForRecord: function(store, record) { - return Ember.guidFor(record); - }, - - find: function(store, type, id) { - var fixtures = this.fixturesForType(type), - fixture; - - Ember.warn("Unable to find fixtures for model type " + type.toString(), fixtures); - - if (fixtures) { - fixture = Ember.A(fixtures).findProperty('id', id); - } - - if (fixture) { - this.simulateRemoteCall(function() { - this.didFindRecord(store, type, fixture, id); - }, this); - } - }, - - findMany: function(store, type, ids) { - var fixtures = this.fixturesForType(type); - - Ember.assert("Unable to find fixtures for model type "+type.toString(), !!fixtures); - - if (fixtures) { - fixtures = fixtures.filter(function(item) { - return ids.indexOf(item.id) !== -1; - }); - } - - if (fixtures) { - this.simulateRemoteCall(function() { - this.didFindMany(store, type, fixtures); - }, this); - } - }, - - findAll: function(store, type) { - var fixtures = this.fixturesForType(type); - - Ember.assert("Unable to find fixtures for model type "+type.toString(), !!fixtures); - - this.simulateRemoteCall(function() { - this.didFindAll(store, type, fixtures); - }, this); - }, - - findQuery: function(store, type, query, array) { - var fixtures = this.fixturesForType(type); - - Ember.assert("Unable to find fixtures for model type "+type.toString(), !!fixtures); - - fixtures = this.queryFixtures(fixtures, query, type); - - if (fixtures) { - this.simulateRemoteCall(function() { - this.didFindQuery(store, type, fixtures, array); - }, this); - } - }, - - createRecord: function(store, type, record) { - var fixture = this.mockJSON(type, record); - - this.updateFixtures(type, fixture); - - this.simulateRemoteCall(function() { - this.didCreateRecord(store, type, record, fixture); - }, this); - }, - - updateRecord: function(store, type, record) { - var fixture = this.mockJSON(type, record); - - this.updateFixtures(type, fixture); - - this.simulateRemoteCall(function() { - this.didUpdateRecord(store, type, record, fixture); - }, this); - }, - - deleteRecord: function(store, type, record) { - var fixture = this.mockJSON(type, record); - - this.deleteLoadedFixture(type, fixture); - - this.simulateRemoteCall(function() { - this.didDeleteRecord(store, type, record); - }, this); - }, - - /* - @private - */ - deleteLoadedFixture: function(type, record) { - var existingFixture = this.findExistingFixture(type, record); - - if(existingFixture) { - var index = type.FIXTURES.indexOf(existingFixture); - type.FIXTURES.splice(index, 1); - return true; - } - }, - - findExistingFixture: function(type, record) { - var fixtures = this.fixturesForType(type); - var id = this.extractId(type, record); - - return this.findFixtureById(fixtures, id); - }, - - findFixtureById: function(fixtures, id) { - return Ember.A(fixtures).find(function(r) { - if(''+get(r, 'id') === ''+id) { - return true; - } else { - return false; - } - }); - }, - - simulateRemoteCall: function(callback, context) { - if (get(this, 'simulateRemoteResponse')) { - // Schedule with setTimeout - Ember.run.later(context, callback, get(this, 'latency')); - } else { - // Asynchronous, but at the of the runloop with zero latency - Ember.run.once(context, callback); - } - } -}); - -})(); - - - -(function() { -/** - @module data - @submodule data-serializers -*/ - -/** - @class RESTSerializer - @constructor - @namespace DS - @extends DS.Serializer -*/ - -var get = Ember.get; - -DS.RESTSerializer = DS.JSONSerializer.extend({ - keyForAttributeName: function(type, name) { - return Ember.String.decamelize(name); - }, - - keyForBelongsTo: function(type, name) { - var key = this.keyForAttributeName(type, name); - - if (this.embeddedType(type, name)) { - return key; - } - - return key + "_id"; - }, - - keyForHasMany: function(type, name) { - var key = this.keyForAttributeName(type, name); - - if (this.embeddedType(type, name)) { - return key; - } - - return this.singularize(key) + "_ids"; - }, - - keyForPolymorphicId: function(key) { - return key; - }, - - keyForPolymorphicType: function(key) { - return key.replace(/_id$/, '_type'); - }, - - extractValidationErrors: function(type, json) { - var errors = {}; - - get(type, 'attributes').forEach(function(name) { - var key = this._keyForAttributeName(type, name); - if (json['errors'].hasOwnProperty(key)) { - errors[name] = json['errors'][key]; - } - }, this); - - return errors; - } -}); - -})(); - - - -(function() { -/*global jQuery*/ - -/** - @module data - @submodule data-adapters -*/ - -var get = Ember.get, set = Ember.set; - -function rejectionHandler(reason) { - Ember.Logger.error(reason, reason.message); - throw reason; -} - -/** - The REST adapter allows your store to communicate with an HTTP server by - transmitting JSON via XHR. Most Ember.js apps that consume a JSON API - should use the REST adapter. - - This adapter is designed around the idea that the JSON exchanged with - the server should be conventional. - - ## JSON Structure - - The REST adapter expects the JSON returned from your server to follow - these conventions. - - ### Object Root - - The JSON payload should be an object that contains the record inside a - root property. For example, in response to a `GET` request for - `/posts/1`, the JSON should look like this: - - ```js - { - "post": { - title: "I'm Running to Reform the W3C's Tag", - author: "Yehuda Katz" - } - } - ``` - - ### Conventional Names - - Attribute names in your JSON payload should be the underscored versions of - the attributes in your Ember.js models. - - For example, if you have a `Person` model: - - ```js - App.Person = DS.Model.extend({ - firstName: DS.attr('string'), - lastName: DS.attr('string'), - occupation: DS.attr('string') - }); - ``` - - The JSON returned should look like this: - - ```js - { - "person": { - "first_name": "Barack", - "last_name": "Obama", - "occupation": "President" - } - } - ``` - - @class RESTAdapter - @constructor - @namespace DS - @extends DS.Adapter -*/ -DS.RESTAdapter = DS.Adapter.extend({ - namespace: null, - bulkCommit: false, - since: 'since', - - serializer: DS.RESTSerializer, - - init: function() { - this._super.apply(this, arguments); - }, - - shouldSave: function(record) { - var reference = get(record, '_reference'); - - return !reference.parent; - }, - - dirtyRecordsForRecordChange: function(dirtySet, record) { - this._dirtyTree(dirtySet, record); - }, - - dirtyRecordsForHasManyChange: function(dirtySet, record, relationship) { - var embeddedType = get(this, 'serializer').embeddedType(record.constructor, relationship.secondRecordName); - - if (embeddedType === 'always') { - relationship.childReference.parent = relationship.parentReference; - this._dirtyTree(dirtySet, record); - } - }, - - _dirtyTree: function(dirtySet, record) { - dirtySet.add(record); - - get(this, 'serializer').eachEmbeddedRecord(record, function(embeddedRecord, embeddedType) { - if (embeddedType !== 'always') { return; } - if (dirtySet.has(embeddedRecord)) { return; } - this._dirtyTree(dirtySet, embeddedRecord); - }, this); - - var reference = record.get('_reference'); - - if (reference.parent) { - var store = get(record, 'store'); - var parent = store.recordForReference(reference.parent); - this._dirtyTree(dirtySet, parent); - } - }, - - createRecord: function(store, type, record) { - var root = this.rootForType(type); - var adapter = this; - var data = {}; - - data[root] = this.serialize(record, { includeId: true }); - - return this.ajax(this.buildURL(root), "POST", { - data: data - }).then(function(json){ - adapter.didCreateRecord(store, type, record, json); - }, function(xhr) { - adapter.didError(store, type, record, xhr); - throw xhr; - }).then(null, rejectionHandler); - }, - - createRecords: function(store, type, records) { - var adapter = this; - - if (get(this, 'bulkCommit') === false) { - return this._super(store, type, records); - } - - var root = this.rootForType(type), - plural = this.pluralize(root); - - var data = {}; - data[plural] = []; - records.forEach(function(record) { - data[plural].push(this.serialize(record, { includeId: true })); - }, this); - - return this.ajax(this.buildURL(root), "POST", { - data: data - }).then(function(json) { - adapter.didCreateRecords(store, type, records, json); - }).then(null, rejectionHandler); - }, - - updateRecord: function(store, type, record) { - var id, root, adapter, data; - - id = get(record, 'id'); - root = this.rootForType(type); - adapter = this; - - data = {}; - data[root] = this.serialize(record); - - return this.ajax(this.buildURL(root, id), "PUT",{ - data: data - }).then(function(json){ - adapter.didUpdateRecord(store, type, record, json); - }, function(xhr) { - adapter.didError(store, type, record, xhr); - throw xhr; - }).then(null, rejectionHandler); - }, - - updateRecords: function(store, type, records) { - var root, plural, adapter, data; - - if (get(this, 'bulkCommit') === false) { - return this._super(store, type, records); - } - - root = this.rootForType(type); - plural = this.pluralize(root); - adapter = this; - - data = {}; - - data[plural] = []; - - records.forEach(function(record) { - data[plural].push(this.serialize(record, { includeId: true })); - }, this); - - return this.ajax(this.buildURL(root, "bulk"), "PUT", { - data: data - }).then(function(json) { - adapter.didUpdateRecords(store, type, records, json); - }).then(null, rejectionHandler); - }, - - deleteRecord: function(store, type, record) { - var id, root, adapter; - - id = get(record, 'id'); - root = this.rootForType(type); - adapter = this; - - return this.ajax(this.buildURL(root, id), "DELETE").then(function(json){ - adapter.didDeleteRecord(store, type, record, json); - }, function(xhr){ - adapter.didError(store, type, record, xhr); - throw xhr; - }).then(null, rejectionHandler); - }, - - deleteRecords: function(store, type, records) { - var root, plural, serializer, adapter, data; - - if (get(this, 'bulkCommit') === false) { - return this._super(store, type, records); - } - - root = this.rootForType(type); - plural = this.pluralize(root); - serializer = get(this, 'serializer'); - adapter = this; - - data = {}; - - data[plural] = []; - records.forEach(function(record) { - data[plural].push(serializer.serializeId( get(record, 'id') )); - }); - - return this.ajax(this.buildURL(root, 'bulk'), "DELETE", { - data: data - }).then(function(json){ - adapter.didDeleteRecords(store, type, records, json); - }).then(null, rejectionHandler); - }, - - find: function(store, type, id) { - var root = this.rootForType(type), adapter = this; - - return this.ajax(this.buildURL(root, id), "GET"). - then(function(json){ - adapter.didFindRecord(store, type, json, id); - }).then(null, rejectionHandler); - }, - - findAll: function(store, type, since) { - var root, adapter; - - root = this.rootForType(type); - adapter = this; - - return this.ajax(this.buildURL(root), "GET",{ - data: this.sinceQuery(since) - }).then(function(json) { - adapter.didFindAll(store, type, json); - }).then(null, rejectionHandler); - }, - - findQuery: function(store, type, query, recordArray) { - var root = this.rootForType(type), - adapter = this; - - return this.ajax(this.buildURL(root), "GET", { - data: query - }).then(function(json){ - adapter.didFindQuery(store, type, json, recordArray); - }).then(null, rejectionHandler); - }, - - findMany: function(store, type, ids, owner) { - var root = this.rootForType(type), - adapter = this; - - ids = this.serializeIds(ids); - - return this.ajax(this.buildURL(root), "GET", { - data: {ids: ids} - }).then(function(json) { - adapter.didFindMany(store, type, json); - }).then(null, rejectionHandler); - }, - - /** - @private - - This method serializes a list of IDs using `serializeId` - - @return {Array} an array of serialized IDs - */ - serializeIds: function(ids) { - var serializer = get(this, 'serializer'); - - return Ember.EnumerableUtils.map(ids, function(id) { - return serializer.serializeId(id); - }); - }, - - didError: function(store, type, record, xhr) { - if (xhr.status === 422) { - var json = JSON.parse(xhr.responseText), - serializer = get(this, 'serializer'), - errors = serializer.extractValidationErrors(type, json); - - store.recordWasInvalid(record, errors); - } else { - this._super.apply(this, arguments); - } - }, - - ajax: function(url, type, hash) { - var adapter = this; - - return new Ember.RSVP.Promise(function(resolve, reject) { - hash = hash || {}; - hash.url = url; - hash.type = type; - hash.dataType = 'json'; - hash.context = adapter; - - if (hash.data && type !== 'GET') { - hash.contentType = 'application/json; charset=utf-8'; - hash.data = JSON.stringify(hash.data); - } - - hash.success = function(json) { - Ember.run(null, resolve, json); - }; - - hash.error = function(jqXHR, textStatus, errorThrown) { - Ember.run(null, reject, errorThrown); - }; - - jQuery.ajax(hash); - }); - }, - - url: "", - - rootForType: function(type) { - var serializer = get(this, 'serializer'); - return serializer.rootForType(type); - }, - - pluralize: function(string) { - var serializer = get(this, 'serializer'); - return serializer.pluralize(string); - }, - - buildURL: function(record, suffix) { - var url = [this.url]; - - Ember.assert("Namespace URL (" + this.namespace + ") must not start with slash", !this.namespace || this.namespace.toString().charAt(0) !== "/"); - Ember.assert("Record URL (" + record + ") must not start with slash", !record || record.toString().charAt(0) !== "/"); - Ember.assert("URL suffix (" + suffix + ") must not start with slash", !suffix || suffix.toString().charAt(0) !== "/"); - - if (!Ember.isNone(this.namespace)) { - url.push(this.namespace); - } - - url.push(this.pluralize(record)); - if (suffix !== undefined) { - url.push(suffix); - } - - return url.join("/"); - }, - - sinceQuery: function(since) { - var query = {}; - query[get(this, 'since')] = since; - return since ? query : null; - } -}); - -})(); - - - -(function() { -/** - Adapters included with Ember-Data. - - @module data - @submodule data-adapters - - @main data-adapters -*/ - -})(); - - - -(function() { -//Copyright (C) 2011 by Living Social, Inc. - -//Permission is hereby granted, free of charge, to any person obtaining a copy of -//this software and associated documentation files (the "Software"), to deal in -//the Software without restriction, including without limitation the rights to -//use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -//of the Software, and to permit persons to whom the Software is furnished to do -//so, subject to the following conditions: - -//The above copyright notice and this permission notice shall be included in all -//copies or substantial portions of the Software. - -//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -//SOFTWARE. - -/** - Ember Data - @module data -*/ - -})(); - - -})(); diff --git a/ajax/libs/ember-data.js/0.13.0-latest20130528/ember-data-latest.min.js b/ajax/libs/ember-data.js/0.13.0-latest20130528/ember-data-latest.min.js deleted file mode 100644 index b2df24fd0..000000000 --- a/ajax/libs/ember-data.js/0.13.0-latest20130528/ember-data-latest.min.js +++ /dev/null @@ -1,16 +0,0 @@ -// ========================================================================== -// Project: Ember Data -// Copyright: ©2011-2012 Tilde Inc. and contributors. -// Portions ©2011 Living Social Inc. and contributors. -// License: Licensed under MIT license (see license.js) -// ========================================================================== - - - -// Version: v0.13 -// Last commit: 610cfec (2013-05-28 08:04:23 -0400) - - -!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]={};for(var i,a=r[e],o=a.deps,s=a.callback,c=[],d=0,u=o.length;u>d;d++)"exports"===o[d]?c.push(i={}):c.push(t(o[d]));var h=s.apply(this,c);return n[e]=i||h}}(),function(){window.DS=Ember.Namespace.create()}(),function(){Ember.set,Ember.onLoad("Ember.Application",function(e){e.initializer({name:"store",initialize:function(e,t){t.register("store:main",t.Store),e.lookup("store:main")}}),e.initializer({name:"injectStore",initialize:function(e,t){t.inject("controller","store","store:main"),t.inject("route","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.Evented,t=Ember.DeferredMixin,r=Ember.run,n=Ember.get,i=Ember.Mixin.create(e,t,{init:function(){this._super.apply(this,arguments),this.one("didLoad",this,function(){r(this,"resolve",this)}),this.one("becameError",this,function(){r(this,"reject",this)}),n(this,"isLoaded")&&this.trigger("didLoad")}});DS.LoadPromise=i}(),function(){var e=Ember.get;Ember.set;var t=DS.LoadPromise;DS.RecordArray=Ember.ArrayProxy.extend(t,{type:null,content:null,isLoaded:!1,isUpdating:!1,store:null,objectAtContent:function(t){var r=e(this,"content"),n=r.objectAt(t),i=e(this,"store");return n?i.recordForReference(n):void 0},materializedObjectAt:function(t){var r=e(this,"content").objectAt(t);if(r)return e(this,"store").recordIsMaterialized(r)?this.objectAt(t):void 0},update:function(){if(!e(this,"isUpdating")){var t=e(this,"store"),r=e(this,"type");t.fetchAll(r,this)}},addReference:function(t){e(this,"content").addObject(t)},removeReference: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(e){this.setProperties({content:Ember.A(e),isLoaded:!0}),Ember.run.once(this,"trigger","didLoad")}})}(),function(){var e=Ember.get,t=Ember.set;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");r.fetchUnloadedReferences(t,n)},replaceContent:function(t,r,n){n=n.map(function(t){return e(t,"_reference")},this),this._super(t,r,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.get("_reference"),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.get("_reference"),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()}),DS.OneToManyChange.ensureSameTransaction(this._changesToSync,o),this._changesToSync.clear()}},createRecord:function(t,r){var n,i=e(this,"owner"),a=e(i,"store"),o=e(this,"type");return r=r||e(i,"transaction"),n=a.createRecord.call(a,o,t,r),this.pushObject(n),n}})}(),function(){var e=Ember.get,t=Ember.set,r=Ember.EnumerableUtils.forEach;DS.Transaction=Ember.Object.extend({init:function(){t(this,"records",Ember.OrderedSet.create())},createRecord:function(t,r){var n=e(this,"store");return n.createRecord(t,r,this)},isEqualOrDefault:function(t){return this===t||t===e(this,"store.defaultTransaction")?!0:void 0},isDefault:Ember.computed(function(){return this===e(this,"store.defaultTransaction")}).volatile(),add:function(t){var r=e(this,"store"),n=e(r,"_adapter"),i=e(n,"serializer");i.eachEmbeddedRecord(t,function(e,t){"load"!==t&&this.add(e)},this),this.adoptRecord(t)},relationships:Ember.computed(function(){var t=Ember.OrderedSet.create(),r=e(this,"records"),n=e(this,"store");return r.forEach(function(r){for(var i=e(r,"_reference"),a=n.relationshipChangesFor(i),o=0;or;r++){var i=e[r];i.data===o&&(t.push(i),i.data=s)}return t},fetchUnloadedReferences:function(e,t){var r=this.unloadedReferences(e);this.fetchMany(r,t)},fetchMany:function(e,t){if(e.length){var r=Ember.MapWithDefault.create({defaultValue:function(){return Ember.A()}});i(e,function(e){r.get(e.type).push(e)}),i(r,function(e){var n=r.get(e),i=a(n,function(e){return e.id}),o=this.adapterForType(e);o.findMany(this,e,i,t)},this)}},hasReferenceForId:function(e,t){return t=u(t),!!this.typeMapFor(e).idToReference[t]},referenceForId:function(e,t){t=u(t);var r=this.typeMapFor(e).idToReference[t];return r||(r=this.createReference(e,t),r.data=o),r},findMany:function(e,t,r,n){if(!Ember.isArray(t)){var i=this.adapterForType(e);return i&&i.findHasMany&&i.findHasMany(this,r,n,t),this.recordArrayManager.createManyArray(e,Ember.A())}var o,s,c,d=a(t,function(t){return"object"!=typeof t&&null!==t?this.referenceForId(e,t):t},this),u=this.unloadedReferences(d),h=this.recordArrayManager.createManyArray(e,Ember.A(d));if(this.loadingRecordArrays,h.loadingRecordsCount(u.length),u.length){for(s=0,c=u.length;c>s;s++)o=u[s],this.recordArrayManager.registerWaitingRecordArray(h,o);this.fetchMany(u,r)}else h.set("isLoaded",!0),Ember.run.once(function(){h.trigger("didLoad")});return h},findQuery:function(e,t){var r=DS.AdapterPopulatedRecordArray.create({type:e,query:t,content:Ember.A([]),store:this}),n=this.adapterForType(e);return n.findQuery(this,e,t,r),r},findAll:function(e){return this.fetchAll(e,this.all(e))},fetchAll:function(e,r){var n=this.adapterForType(e),i=this.typeMapFor(e).metadata.since;return t(r,"isUpdating",!0),n.findAll(this,e,i),r},metaForType:function(e,r,n){var i=this.typeMapFor(e).metadata;t(i,r,n)},didUpdateAll:function(e){var r=this.typeMapFor(e).findAllCache;t(r,"isUpdating",!1)},all:function(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){3===arguments.length?this.findQuery(e,t):2===arguments.length&&(r=t);var n=DS.FilteredRecordArray.create({type:e,content:Ember.A([]),store:this,manager:this.recordArrayManager,filterFunction:r});return this.recordArrayManager.registerFilteredRecordArray(n,e,r),n},recordIsLoaded:function(e,t){return this.hasReferenceForId(e,t)?"object"==typeof this.referenceForId(e,t).data:!1},dataWasUpdated:function(t,r,n){e(n,"isDeleted")||"object"==typeof r.data&&this.recordArrayManager.referenceDidChange(r)},save:function(){r(this,"commitDefaultTransaction")},commit:Ember.aliasMethod("save"),commitDefaultTransaction:function(){e(this,"defaultTransaction").commit()},scheduleSave:function(t){e(this,"currentTransaction").add(t),r(this,"flushSavedRecords")},flushSavedRecords:function(){e(this,"currentTransaction").commit(),t(this,"currentTransaction",this.transaction())},didSaveRecord:function(e,t){t?(this.updateId(e,t),this.updateRecordData(e,t)):this.didUpdateAttributes(e),e.adapterDidCommit()},didSaveRecords:function(e,t){var r=0;e.forEach(function(e){this.didSaveRecord(e,t&&t[r++])},this)},recordWasInvalid:function(e,t){e.adapterDidInvalidate(t)},recordWasError:function(e){e.adapterDidError()},didUpdateAttribute:function(e,t,r){e.adapterDidUpdateAttribute(t,r)},didUpdateAttributes:function(e){e.eachAttribute(function(t){this.didUpdateAttribute(e,t)},this)},didUpdateRelationship:function(t,r){var n=e(t,"_reference").clientId,i=this.relationshipChangeFor(n,r);i&&i.adapterDidUpdate()},didUpdateRelationships:function(t){var r=this.relationshipChangesFor(e(t,"_reference"));for(var n in r)r.hasOwnProperty(n)&&r[n].adapterDidUpdate()},didReceiveId:function(t,r){var n=this.typeMapFor(t.constructor),i=e(t,"clientId");e(t,"id"),n.idToCid[r]=i,this.clientIdToId[i]=r},updateRecordData:function(t,r){e(t,"_reference").data=r,t.didChangeData()},updateId:function(t,r){var n=t.constructor,i=this.typeMapFor(n),a=e(t,"_reference"),o=(e(t,"id"),this.preprocessData(n,r));i.idToReference[o]=a,a.id=o},preprocessData:function(e,t){return this.adapterForType(e).extractId(e,t)},typeMapFor:function(t){var r,n=e(this,"typeMaps"),i=Ember.guidFor(t);return(r=n[i])?r:(r={idToReference:{},references:[],metadata:{}},n[i]=r,r)},load:function(e,t,n){var i;("number"==typeof t||"string"==typeof t)&&(i=t,t=n,n=null),n&&n.id?i=n.id:void 0===i&&(i=this.preprocessData(e,t)),i=u(i);var a=this.referenceForId(e,i);return a.record&&r(a.record,"loadedData"),a.data=t,a.prematerialized=n,this.recordArrayManager.referenceDidChange(a),a},loadMany:function(e,t,r){return void 0===r&&(r=t,t=a(r,function(t){return this.preprocessData(e,t)},this)),a(t,function(t,n){return this.load(e,t,r[n])},this)},loadHasMany:function(e,r,n){var i=e.get(r+".type"),o=a(n,function(e){return{id:e,type:i}});e.materializeHasMany(r,o),e.hasManyDidChange(r);var s=e.cacheFor(r);s&&(t(s,"isLoaded",!0),s.trigger("didLoad"))},createReference:function(e,t){var r=this.typeMapFor(e),n=r.idToReference,i={id:t,clientId:this.clientIdCounter++,type:e};return t&&(n[t]=i),r.references.push(i),i},materializeRecord:function(t){var r=t.type._create({id:t.id,store:this,_reference:t});return t.record=r,e(this,"defaultTransaction").adoptRecord(r),r.loadingData(),"object"==typeof t.data&&r.loadedData(),r},dematerializeRecord:function(t){var r=e(t,"_reference"),n=r.type,i=r.id,a=this.typeMapFor(n);t.updateRecordArrays(),i&&delete a.idToReference[i];var o=a.references.indexOf(r);a.references.splice(o,1)},willDestroy:function(){e(DS,"defaultStore")===this&&t(DS,"defaultStore",null)},addRelationshipChangeFor:function(e,t,r,n,i){var a=e.clientId,o=r?r.clientId: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]},relationshipChangeFor:function(e,t,r,n,i){var a=e.clientId,o=r?r.clientId:r,s=this.relationshipChanges,c=t+n;return a in s&&o in s[a]?i?s[a][o][c][i]:s[a][o][c].add||s[a][o][c].remove:void 0},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},relationshipChangesFor:function(e){var t=[];if(!e)return t;var r=this.relationshipChangePairsFor(e);return i(r,function(e){var r=e.add,n=e.remove;r&&t.push(r),n&&t.push(n)}),t},adapterForType:function(e){this._adaptersMap=this.createInstanceMapFor("adapters");var t=this._adaptersMap.get(e);return t?t:this.get("_adapter")},recordAttributeDidChange:function(e,t,r,n){var i=e.record,a=new Ember.OrderedSet,o=this.adapterForType(i.constructor);o.dirtyRecordsForAttributeChange&&o.dirtyRecordsForAttributeChange(a,i,t,r,n),a.forEach(function(e){e.adapterDidDirty()})},recordBelongsToDidChange:function(e,t,r){var n=this.adapterForType(t.constructor);n.dirtyRecordsForBelongsToChange&&n.dirtyRecordsForBelongsToChange(e,t,r)},recordHasManyDidChange:function(e,t,r){var n=this.adapterForType(t.constructor);n.dirtyRecordsForHasManyChange&&n.dirtyRecordsForHasManyChange(e,t,r)}}),DS.Store.reopenClass({registerAdapter:DS._Mappable.generateMapFunctionFor("adapters",function(e,t,r){r.set(e,t)}),transformMapKey:function(t){if("string"==typeof t){var r;return r=e(Ember.lookup,t)}return t},transformMapValue:function(e,t){return Ember.Object.detect(t)?t.create():t}})}(),function(){var e=Ember.get,t=Ember.set,r=Ember.run.once,n=Ember.ArrayPolyfills.map,i=Ember.computed(function(t){var r=e(this,"parentState");return r?e(r,t):void 0}).property(),a=function(e){for(var t in e)if(e.hasOwnProperty(t)&&e[t])return!0;return!1},o=function(t){var r=e(t,"record");r.materializeData()},s=function(t,r){r.oldValue=e(e(t,"record"),r.name);var n=DS.AttributeChange.createChange(r);e(t,"record")._changesToSync[r.name]=n},c=function(t,r){var n=e(t,"record")._changesToSync[r.name];n.value=e(e(t,"record"),r.name),n.sync()};DS.State=Ember.State.extend({isLoading:i,isLoaded:i,isReloading:i,isDirty:i,isSaving:i,isDeleted:i,isError:i,isNew:i,isValid:i,dirtyType:i});var d=DS.State.extend({initialState:"uncommitted",isDirty:!0,uncommitted:DS.State.extend({willSetProperty:s,didSetProperty:c,becomeDirty:Ember.K,willCommit:function(e){e.transitionTo("inFlight")},becameClean:function(t){var r=e(t,"record");r.withTransaction(function(e){e.remove(r)}),t.transitionTo("loaded.materializing")},becameInvalid:function(e){e.transitionTo("invalid")},rollback:function(t){e(t,"record").rollback()}}),inFlight:DS.State.extend({isSaving:!0,enter:function(t){var r=e(t,"record");r.becameInFlight()},materializingData:function(r){t(r,"lastDirtyType",e(this,"dirtyType")),r.transitionTo("materializing")},didCommit:function(t){var r=e(this,"dirtyType"),n=e(t,"record");n.withTransaction(function(e){e.remove(n)}),t.transitionTo("saved"),t.send("invokeLifecycleCallbacks",r)},didChangeData:o,becameInvalid:function(r,n){var i=e(r,"record");t(i,"errors",n),r.transitionTo("invalid"),r.send("invokeLifecycleCallbacks")},becameError:function(e){e.transitionTo("error"),e.send("invokeLifecycleCallbacks")}}),invalid:DS.State.extend({isValid:!1,exit:function(t){var r=e(t,"record");r.withTransaction(function(e){e.remove(r)})},deleteRecord:function(t){t.transitionTo("deleted"),e(t,"record").clearRelationships()},willSetProperty:s,didSetProperty:function(r,n){var i=e(r,"record"),o=e(i,"errors"),s=n.name;t(o,s,null),a(o)||r.send("becameValid"),c(r,n)},becomeDirty:Ember.K,rollback:function(e){e.send("becameValid"),e.send("rollback")},becameValid:function(e){e.transitionTo("uncommitted")},invokeLifecycleCallbacks:function(t){var r=e(t,"record");r.trigger("becameInvalid",r)}})}),u=d.create({dirtyType:"created",isNew:!0}),h=d.create({dirtyType:"updated"});u.states.uncommitted.reopen({deleteRecord:function(t){var r=e(t,"record");r.clearRelationships(),t.transitionTo("deleted.saved")}}),u.states.uncommitted.reopen({rollback:function(e){this._super(e),e.transitionTo("deleted.saved")}}),h.states.uncommitted.reopen({deleteRecord:function(t){var r=e(t,"record");t.transitionTo("deleted"),r.clearRelationships()}});var l={rootState:Ember.State.create({isLoading:!1,isLoaded:!1,isReloading:!1,isDirty:!1,isSaving:!1,isDeleted:!1,isError:!1,isNew:!1,isValid:!0,empty:DS.State.create({loadingData:function(e){e.transitionTo("loading")},loadedData:function(e){e.transitionTo("loaded.created")}}),loading:DS.State.create({isLoading:!0,loadedData:o,materializingData:function(e){e.transitionTo("loaded.materializing.firstTime")},becameError:function(e){e.transitionTo("error"),e.send("invokeLifecycleCallbacks")}}),loaded:DS.State.create({initialState:"saved",isLoaded:!0,materializing:DS.State.create({willSetProperty:Ember.K,didSetProperty:Ember.K,didChangeData:o,finishedMaterializing:function(e){e.transitionTo("loaded.saved")},firstTime:DS.State.create({isLoaded:!1,exit:function(t){var n=e(t,"record");r(function(){n.trigger("didLoad")})}})}),reloading:DS.State.create({isReloading:!0,enter:function(t){var r=e(t,"record"),n=e(r,"store");n.reloadRecord(r)},exit:function(t){var n=e(t,"record");r(n,"trigger","didReload")},loadedData:o,materializingData:function(e){e.transitionTo("loaded.materializing")}}),saved:DS.State.create({willSetProperty:s,didSetProperty:c,didChangeData:o,loadedData:o,reloadRecord:function(e){e.transitionTo("loaded.reloading")},materializingData:function(e){e.transitionTo("loaded.materializing")},becomeDirty:function(e){e.transitionTo("updated")},deleteRecord:function(t){t.transitionTo("deleted"),e(t,"record").clearRelationships()},unloadRecord:function(t){var r=e(t,"record");r.clearRelationships(),t.transitionTo("deleted.saved")},didCommit:function(t){var r=e(t,"record");r.withTransaction(function(e){e.remove(r)}),t.send("invokeLifecycleCallbacks",e(t,"lastDirtyType"))},invokeLifecycleCallbacks:function(t,r){var n=e(t,"record");"created"===r?n.trigger("didCreate",n):n.trigger("didUpdate",n),n.trigger("didCommit",n)}}),created:u,updated:h}),deleted:DS.State.create({initialState:"uncommitted",dirtyType:"deleted",isDeleted:!0,isLoaded:!0,isDirty:!0,setup:function(t){var r=e(t,"record"),n=e(r,"store");n.recordArrayManager.remove(r)},uncommitted:DS.State.create({willCommit:function(e){e.transitionTo("inFlight")},rollback:function(t){e(t,"record").rollback()},becomeDirty:Ember.K,becameClean:function(t){var r=e(t,"record");r.withTransaction(function(e){e.remove(r)}),t.transitionTo("loaded.materializing")}}),inFlight:DS.State.create({isSaving:!0,enter:function(t){var r=e(t,"record");r.becameInFlight()},didCommit:function(t){var r=e(t,"record");r.withTransaction(function(e){e.remove(r)}),t.transitionTo("saved"),t.send("invokeLifecycleCallbacks")}}),saved:DS.State.create({isDirty:!1,setup:function(t){var r=e(t,"record"),n=e(r,"store");n.dematerializeRecord(r)},invokeLifecycleCallbacks:function(t){var r=e(t,"record");r.trigger("didDelete",r),r.trigger("didCommit",r)}})}),error:DS.State.create({isError:!0,invokeLifecycleCallbacks:function(t){var r=e(t,"record");r.trigger("becameError",r)}})})};DS.StateManager=Ember.StateManager.extend({record:null,initialState:"rootState",states:l,unhandledEvent:function(t,r){var i,a=t.get("record"),o=[].slice.call(arguments,2);throw i="Attempted to handle event `"+r+"` ",i+="on "+a.toString()+" while in state ",i+=e(t,"currentState.path")+". Called with ",i+=n.call(o,function(e){return Ember.inspect(e)}).join(", "),new Ember.Error(i)}})}(),function(){var e=DS.LoadPromise,t=Ember.get,r=Ember.set,n=Ember.EnumerableUtils.map,i=Ember.computed(function(e){return t(t(this,"stateManager.currentState"),e)}).property("stateManager.currentState").readOnly();DS.Model=Ember.Object.extend(Ember.Evented,e,{isLoading:i,isLoaded:i,isReloading:i,isDirty:i,isSaving:i,isDeleted:i,isError:i,isNew:i,isValid:i,dirtyType:i,clientId:null,id:null,transaction:null,stateManager:null,errors:null,serialize:function(e){var r=t(this,"store");return r.serialize(this,e)},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.setupData(),this._data}).property(),materializeData:function(){this.send("materializingData"),t(this,"store").materializeData(this),this.suspendRelationshipObservers(function(){this.notifyPropertyChange("data")})},_data:null,init:function(){this._super();var e=DS.StateManager.create({record:this});r(this,"stateManager",e),this._setup(),e.goToState("empty")},_setup:function(){this._changesToSync={}},send:function(e,r){return t(this,"stateManager").send(e,r)},withTransaction:function(e){var r=t(this,"transaction");r&&e(r)},loadingData:function(){this.send("loadingData")},loadedData:function(){this.send("loadedData")},didChangeData:function(){this.send("didChangeData")},deleteRecord:function(){this.send("deleteRecord")},unloadRecord:function(){this.send("unloadRecord")},clearRelationships:function(){this.eachRelationship(function(e,t){"belongsTo"===t.kind?r(this,e,null):"hasMany"===t.kind&&this.clearHasMany(t)},this)},updateRecordArrays:function(){var e=t(this,"store");e&&e.dataWasUpdated(this.constructor,t(this,"_reference"),this)},adapterDidCommit:function(){var e=t(this,"data").attributes;t(this.constructor,"attributes").forEach(function(r){e[r]=t(this,r)},this),this.send("didCommit"),this.updateRecordArraysLater()},adapterDidDirty:function(){this.send("becomeDirty"),this.updateRecordArraysLater()},dataDidChange:Ember.observer(function(){this.reloadHasManys(),this.send("finishedMaterializing")},"data"),reloadHasManys:function(){var e=t(this.constructor,"relationshipsByName");this.updateRecordArraysLater(),e.forEach(function(e,t){"hasMany"===t.kind&&this.hasManyDidChange(t.key)},this)},hasManyDidChange:function(e){var i=this.cacheFor(e);if(i){var a=t(this.constructor,"relationshipsByName").get(e).type,o=t(this,"store"),s=this._data.hasMany[e]||[],c=n(s,function(e){return"object"==typeof e?e.clientId?e:o.referenceForId(e.type,e.id):o.referenceForId(a,e)});r(i,"content",Ember.A(c))}},updateRecordArraysLater:function(){Ember.run.once(this,this.updateRecordArrays)},setupData:function(){this._data={attributes:{},belongsTo:{},hasMany:{},id:null}},materializeId:function(e){r(this,"id",e)},materializeAttributes:function(e){this._data.attributes=e},materializeAttribute:function(e,t){this._data.attributes[e]=t},materializeHasMany:function(e,t){var r=typeof t;if(t&&"string"!==r&&t.length>1&&Ember.assert("materializeHasMany expects tuples, references or opaque token, not "+t[0],t[0].hasOwnProperty("id")&&t[0].type),"string"===r)this._data.hasMany[e]=t;else{var n=t;t&&Ember.isArray(t)&&(n=this._convertTuplesToReferences(t)),this._data.hasMany[e]=n}},materializeBelongsTo:function(e,t){t&&Ember.assert("materializeBelongsTo expects a tuple or a reference, not a "+t,!t||t.hasOwnProperty("id")&&t.hasOwnProperty("type")),this._data.belongsTo[e]=t},_convertTuplesToReferences:function(e){return n(e,function(e){return this._convertTupleToReference(e)},this)},_convertTupleToReference:function(e){var r=t(this,"store");return e.clientId?e:r.referenceForId(e.type,e.id)},rollback:function(){this._setup(),this.send("becameClean"),this.suspendRelationshipObservers(function(){this.notifyPropertyChange("data")})},toStringExtension:function(){return t(this,"id")},suspendRelationshipObservers:function(e,r){var n=t(this.constructor,"relationshipNames").belongsTo,i=this;try{this._suspendedRelationships=!0,Ember._suspendObservers(i,n,null,"belongsToDidChange",function(){Ember._suspendBeforeObservers(i,n,null,"belongsToWillChange",function(){e.call(r||i)})})}finally{this._suspendedRelationships=!1}},becameInFlight:function(){},resolveOn:function(e){var t=this;return new Ember.RSVP.Promise(function(r,n){function i(){this.off("becameError",a),this.off("becameInvalid",a),r(this)}function a(){this.off(e,i),n(this)}t.one(e,i),t.one("becameError",a),t.one("becameInvalid",a)})},save:function(){return this.get("store").scheduleSave(this),this.resolveOn("didCommit")},reload:function(){return this.send("reloadRecord"),this.resolveOn("didReload")},adapterDidUpdateAttribute:function(e,r){void 0!==r?(t(this,"data.attributes")[e]=r,this.notifyPropertyChange(e)):(r=t(this,e),t(this,"data.attributes")[e]=r),this.updateRecordArraysLater()},adapterDidInvalidate:function(e){this.send("becameInvalid",e)},adapterDidError:function(){this.send("becameError")},trigger:function(e){Ember.tryInvoke(this,e,[].slice.call(arguments,1)),this._super.apply(this,arguments)}});var a=function(e){return function(){var r=t(DS,"defaultStore"),n=[].slice.call(arguments);return n.unshift(this),r[e].apply(r,n)}};DS.Model.reopenClass({_create:DS.Model.create,create:function(){throw new Ember.Error("You should not call `create` on a model. Instead, call `createRecord` with the attributes you would like to set.")},find:a("find"),all:a("all"),query:a("findQuery"),filter:a("filter"),createRecord:a("createRecord")})}(),function(){function e(e,r,n){var i=t(e,"data").attributes,a=i[n];return void 0===a&&(a="function"==typeof r.defaultValue?r.defaultValue():r.defaultValue),a}var t=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})}),DS.Model.reopen({eachAttribute:function(e,r){t(this.constructor,"attributes").forEach(function(t,n){e.call(r,t,n)},r)},attributeWillChange:Ember.beforeObserver(function(e,r){var n=t(e,"_reference"),i=t(e,"store");e.send("willSetProperty",{reference:n,store:i,name:r})}),attributeDidChange:Ember.observer(function(e,t){e.send("didSetProperty",{name:t})})}),DS.attr=function(t,r){r=r||{};var n={type:t,isAttribute:!0,options:r};return Ember.computed(function(t,n){return arguments.length>1||(n=e(this,r,t)),n}).property("data").meta(n)}}(),function(){var e=DS.AttributeChange=function(e){this.reference=e.reference,this.store=e.store,this.name=e.name,this.oldValue=e.oldValue};e.createChange=function(t){return new e(t)},e.prototype={sync:function(){this.store.recordAttributeDidChange(this.reference,this.name,this.value,this.oldValue),this.destroy()},destroy:function(){var e=this.reference.record;delete e._changesToSync[this.name]}}}(),function(){var e=Ember.get,t=Ember.set,r=Ember.EnumerableUtils.forEach;DS.RelationshipChange=function(e){this.parentReference=e.parentReference,this.childReference=e.childReference,this.firstRecordReference=e.firstRecordReference,this.firstRecordKind=e.firstRecordKind,this.firstRecordName=e.firstRecordName,this.secondRecordReference=e.secondRecordReference,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.type;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({parentReference:t,childReference:e,firstRecordReference: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({parentReference:e,childReference:t,secondRecordReference: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({parentReference:t,childReference:e,firstRecordReference:e,secondRecordReference: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({parentReference:t,childReference:e,firstRecordReference:e,secondRecordReference: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(t,r,n,i){if("add"===t.changeType&&r.recordIsMaterialized(n)){var a=r.recordForReference(n),o=e(a,i);if(o){var s=DS.OneToOneChange.createChange(n,o.get("_reference"),r,{parentType:t.parentType,hasManyName:t.hasManyName,changeType:"remove",key:t.key});r.addRelationshipChangeFor(n,i,t.parentReference,null,s),s.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({parentReference:t,childReference:e,firstRecordReference:e,secondRecordReference: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(t,r,n,i){var a=n.record;if("add"===t.changeType&&a){var o=e(a,i);if(o){var s=DS.OneToManyChange.createChange(n,o.get("_reference"),r,{parentType:t.parentType,hasManyName:t.hasManyName,changeType:"remove",key:t.key});r.addRelationshipChangeFor(n,i,t.parentReference,s.getSecondRecordName(),s),s.sync()}}},DS.OneToManyChange.ensureSameTransaction=function(e){var t=Ember.A();return r(e,function(e){t.addObject(e.getSecondRecord()),t.addObject(e.getFirstRecord())}),DS.Transaction.ensureSameTransaction(t)},DS.RelationshipChange.prototype={getSecondRecordName:function(){var e,t=this.secondRecordName;if(!t){if(e=this.secondRecordReference,!e)return;var r=this.firstRecordReference.type,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.childReference,t=this.getFirstRecordName(),r=this.getSecondRecordName(),n=this.store;n.removeRelationshipChangeFor(e,t,this.parentReference,r,this.changeType)},getByReference:function(e){return this.store,e?e.record?e.record:void 0:e},getSecondRecord:function(){return this.getByReference(this.secondRecordReference)},getFirstRecord:function(){return this.getByReference(this.firstRecordReference)},ensureSameTransaction:function(){var e=this.getFirstRecord(),t=this.getSecondRecord(),r=DS.Transaction.ensureSameTransaction([e,t]);return this.transaction=r,r},callChangeEvents:function(){var t=this.getFirstRecord(),r=this.getSecondRecord(),n=new Ember.OrderedSet;r&&e(r,"isLoaded")&&this.store.recordHasManyDidChange(n,r,this),t&&this.store.recordBelongsToDidChange(n,t,this),n.forEach(function(e){e.adapterDidDirty()})},coalesce:function(){var e=this.store.relationshipChangePairsFor(this.firstRecordReference);r(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 r=this.getSecondRecordName(),n=this.getFirstRecordName(),i=this.getFirstRecord(),a=this.getSecondRecord();this.ensureSameTransaction(),this.callChangeEvents(),a&&i&&("belongsTo"===this.secondRecordKind?a.suspendRelationshipObservers(function(){t(a,r,i)}):"hasMany"===this.secondRecordKind&&a.suspendRelationshipObservers(function(){e(a,r).addObject(i)})),i&&a&&e(i,n)!==a&&("belongsTo"===this.firstRecordKind?i.suspendRelationshipObservers(function(){t(i,n,a)}):"hasMany"===this.firstRecordKind&&i.suspendRelationshipObservers(function(){e(i,n).addObject(a)})),this.coalesce()},DS.RelationshipChangeRemove.prototype.changeType="remove",DS.RelationshipChangeRemove.prototype.sync=function(){var r=this.getSecondRecordName(),n=this.getFirstRecordName(),i=this.getFirstRecord(),a=this.getSecondRecord();this.ensureSameTransaction(i,a,r,n),this.callChangeEvents(),a&&i&&("belongsTo"===this.secondRecordKind?a.suspendRelationshipObservers(function(){t(a,r,null)}):"hasMany"===this.secondRecordKind&&a.suspendRelationshipObservers(function(){e(a,r).removeObject(i)})),i&&e(i,n)&&("belongsTo"===this.firstRecordKind?i.suspendRelationshipObservers(function(){t(i,n,null)}):"hasMany"===this.firstRecordKind&&i.suspendRelationshipObservers(function(){e(i,n).removeObject(a)})),this.coalesce()}}(),function(){var e=Ember.get,t=(Ember.set,Ember.isNone);DS.belongsTo=function(r,n){n=n||{};var i={type:r,isRelationship:!0,options:n,kind:"belongsTo"};return Ember.computed(function(n,i){if("string"==typeof r&&(r=e(this,r,!1)||e(Ember.lookup,r)),2===arguments.length)return void 0===i?null:i;var a,o=e(this,"data").belongsTo,s=e(this,"store");return a=o[n],t(a)?null:a.clientId?s.recordForReference(a):s.findById(a.type,a.id)}).property("data").meta(i)},DS.Model.reopen({belongsToWillChange:Ember.beforeObserver(function(t,r){if(e(t,"isLoaded")){var n=e(t,r),i=e(t,"_reference"),a=e(t,"store");if(n){var o=DS.RelationshipChange.createChange(i,e(n,"_reference"),a,{key:r,kind:"belongsTo",changeType:"remove"});o.sync(),this._changesToSync[r]=o}}}),belongsToDidChange:Ember.immediateObserver(function(t,r){if(e(t,"isLoaded")){var n=e(t,r);if(n){var i=e(t,"_reference"),a=e(t,"store"),o=DS.RelationshipChange.createChange(i,e(n,"_reference"),a,{key:r,kind:"belongsTo",changeType:"add"});o.sync(),this._changesToSync[r]&&DS.OneToManyChange.ensureSameTransaction([o,this._changesToSync[r]],a)}}delete this._changesToSync[r]})})}(),function(){function e(e,i){var a=(t(e,"store"),t(e,"data").hasMany),o=a[i.key];if(o){var s=e.constructor.inverseFor(i.key);s&&n(o,function(t){var n;(n=t.record)&&e.suspendRelationshipObservers(function(){r(n,s.name,null)})})}}var t=Ember.get,r=Ember.set,n=Ember.EnumerableUtils.forEach,i=function(e,n){n=n||{};var i={type:e,isRelationship:!0,options:n,kind:"hasMany"};return Ember.computed(function(a){var o,s,c=t(this,"data").hasMany,d=t(this,"store");return"string"==typeof e&&(e=t(this,e,!1)||t(Ember.lookup,e)),o=c[a],s=d.findMany(e,o,this,i),r(s,"owner",this),r(s,"name",a),r(s,"isPolymorphic",n.polymorphic),s}).property().meta(i)};DS.hasMany=function(e,t){return i(e,t)},DS.Model.reopen({clearHasMany:function(t){var r=this.cacheFor(t.name);r?r.clear():e(this,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.isAttribute&&(Ember.addObserver(e,t,null,"attributeDidChange"),Ember.addBeforeObserver(e,t,null,"attributeWillChange")),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,a,o=this.metaForProperty(t).options;if(o.inverse)i=o.inverse,a=Ember.get(n,"relationshipsByName").get(i).kind;else{var s=r(this,n);if(0===s.length)return null;i=s[0].name,a=s[0].kind}return{type:n,name:i,kind:a}},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 t,r=Ember.Map.create();return this.eachComputedProperty(function(n,i){i.isRelationship&&(i.key=n,t=i.type,"string"==typeof t&&(t=e(this,t,!1)||e(Ember.lookup,t),i.type=t),r.set(n,i))}),r}),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.changedReferences=[]},referenceDidChange:function(e){this.changedReferences.push(e),t(this,this.updateRecordArrays)},recordArraysForReference:function(e){return e.recordArrays=e.recordArrays||Ember.OrderedSet.create(),e.recordArrays},updateRecordArrays:function(){r(this.changedReferences,function(t){var n,i=t.type,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.changedReferences=[]},updateRecordArray:function(e,t,r,n){var i,a;t?(a=this.store.recordForReference(n),i=t(a)):i=!0;var o=this.recordArraysForReference(n);i?(o.add(e),e.addReference(n)):i||(o.remove(e),e.removeReference(n))},remove:function(t){var r=e(t,"_reference"),n=r.recordArrays||[];n.forEach(function(e){e.removeReference(r)})},updateFilter:function(t,r,n){for(var i,a,o,s,c=this.store.typeMapFor(r),d=c.references,u=0,h=d.length;h>u;u++)i=d[u],o=!1,a=i.data,"object"==typeof a&&((s=i.record)?e(s,"isDeleted")||(o=!0):o=!0,o&&this.updateRecordArray(t,n,r,i))},createManyArray:function(e,t){var r=DS.ManyArray.create({type:e,content:t,store:this.store});return t.forEach(function(e){var t=this.recordArraysForReference(e);t.add(r)},this),r},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=t.loadingRecordArrays||[];r.push(e),t.loadingRecordArrays=r}})}(),function(){function e(e){return function(){throw new Ember.Error("Your serializer "+this.toString()+" does not implement the required method "+e)}}var t=Ember.get,r=(Ember.set,Ember.ArrayPolyfills.map),n=Ember.isNone;DS.Serializer=Ember.Object.extend({init:function(){this.mappings=Ember.Map.create(),this.aliases=Ember.Map.create(),this.configurations=Ember.Map.create(),this.globalConfigurations={}},extract:e("extract"),extractMany:e("extractMany"),extractId:e("extractId"),extractAttribute:e("extractAttribute"),extractHasMany:e("extractHasMany"),extractBelongsTo:e("extractBelongsTo"),extractRecordRepresentation:function(e,t,r,i){var a,o={};return a=i?e.sideload(t,r):e.load(t,r),this.eachEmbeddedHasMany(t,function(t,i){var s=this.extractEmbeddedData(r,this.keyFor(i));n(s)||this.extractEmbeddedHasMany(e,i,s,a,o)},this),this.eachEmbeddedBelongsTo(t,function(t,i){var s=this.extractEmbeddedData(r,this.keyFor(i));n(s)||this.extractEmbeddedBelongsTo(e,i,s,a,o)},this),e.prematerialize(a,o),a},extractEmbeddedHasMany:function(e,t,n,i,a){var o=r.call(n,function(r){if(r){var n=this.extractEmbeddedType(t,r),a=this.extractRecordRepresentation(e,n,r,!0),o=this.embeddedType(i.type,t.key);"always"===o&&(a.parent=i);var s=t.parentType,c=s.inverseFor(t.key);if(c){var d=c.name;a.prematerialized[d]=i}return a}},this);a[t.key]=o},extractEmbeddedBelongsTo:function(e,t,r,n,i){var a=this.extractEmbeddedType(t,r),o=this.extractRecordRepresentation(e,a,r,!0);i[t.key]=o;var s=this.embeddedType(n.type,t.key);"always"===s&&(o.parent=n)},extractEmbeddedType:function(e){return e.type},extractEmbeddedData:e(),serialize:function(e,r){r=r||{};var n,i=this.createSerializedForm();return r.includeId&&(n=t(e,"id"))&&this._addId(i,e.constructor,n),r.includeType&&this.addType(i,e.constructor),this.addAttributes(i,e),this.addRelationships(i,e),i},serializeValue:function(e,t){var r=this.transforms?this.transforms[t]:null;return r.serialize(e)},serializeId:function(e){return isNaN(e)?e:+e},addAttributes:function(e,t){t.eachAttribute(function(r,n){this._addAttribute(e,t,r,n.type)},this)},addAttribute:e("addAttribute"),addId:e("addId"),addType:Ember.K,createSerializedForm:function(){return{}},addRelationships:function(e,t){t.eachRelationship(function(r,n){"belongsTo"===n.kind?this._addBelongsTo(e,t,r,n):"hasMany"===n.kind&&this._addHasMany(e,t,r,n)},this)},addBelongsTo:e("addBelongsTo"),addHasMany:e("addHasMany"),keyForAttributeName:function(e,t){return t},primaryKey:function(){return"id"},keyForBelongsTo:function(e,t){return this.keyForAttributeName(e,t)},keyForHasMany:function(e,t){return this.keyForAttributeName(e,t)},materialize:function(e,r,n){var i;Ember.isNone(t(e,"id"))&&(i=n&&n.hasOwnProperty("id")?n.id:this.extractId(e.constructor,r),e.materializeId(i)),this.materializeAttributes(e,r,n),this.materializeRelationships(e,r,n)},deserializeValue:function(e,t){var r=this.transforms?this.transforms[t]:null;return r.deserialize(e)},materializeAttributes:function(e,t,r){e.eachAttribute(function(n,i){r&&r.hasOwnProperty(n)?e.materializeAttribute(n,r[n]):this.materializeAttribute(e,t,n,i.type)},this)},materializeAttribute:function(e,t,r,n){var i=this.extractAttribute(e.constructor,t,r);i=this.deserializeValue(i,n),e.materializeAttribute(r,i)},materializeRelationships:function(e,t,r){e.eachRelationship(function(n,i){if("hasMany"===i.kind)if(r&&r.hasOwnProperty(n)){var a=this._convertPrematerializedHasMany(i.type,r[n]);e.materializeHasMany(n,a)}else this.materializeHasMany(n,e,t,i,r);else if("belongsTo"===i.kind)if(r&&r.hasOwnProperty(n)){var o=this._convertTuple(i.type,r[n]);e.materializeBelongsTo(n,o)}else this.materializeBelongsTo(n,e,t,i,r)},this)},materializeHasMany:function(e,t,r,n){var i=t.constructor,a=this._keyForHasMany(i,n.key),o=this.extractHasMany(i,r,a),s=o;o&&Ember.isArray(o)&&(s=this._convertTuples(n.type,o)),t.materializeHasMany(e,s)},materializeBelongsTo:function(e,t,r,i){var a,o=t.constructor,s=this._keyForBelongsTo(o,i.key),c=null;a=i.options&&i.options.polymorphic?this.extractBelongsToPolymorphic(o,r,s):this.extractBelongsTo(o,r,s),n(a)||(c=this._convertTuple(i.type,a)),t.materializeBelongsTo(e,c)},_convertPrematerializedHasMany:function(e,t){var r;return r="string"==typeof t?t:this._convertTuples(e,t)},_convertTuples:function(e,t){return r.call(t,function(t){return this._convertTuple(e,t)},this)},_convertTuple:function(e,t){var r;return"object"==typeof t?DS.Model.detect(t.type)?t:(r=this.typeFromAlias(t.type),{id:t.id,type:r}):{id:t,type:e}},_primaryKey:function(e){var t=this.configurationForType(e),r=t&&t.primaryKey;return r?r:this.primaryKey(e)},_addAttribute:function(e,r,n,i){var a=this._keyForAttributeName(r.constructor,n),o=t(r,n);this.addAttribute(e,a,this.serializeValue(o,i))},_addId:function(e,t,r){var n=this._primaryKey(t);this.addId(e,n,this.serializeId(r))},_keyForAttributeName:function(e,t){return this._keyFromMappingOrHook("keyForAttributeName",e,t)},_keyForBelongsTo:function(e,t){return this._keyFromMappingOrHook("keyForBelongsTo",e,t)},keyFor:function(e){var t=e.parentType,r=e.key;switch(e.kind){case"belongsTo":return this._keyForBelongsTo(t,r);case"hasMany":return this._keyForHasMany(t,r)}},_keyForHasMany:function(e,t){return this._keyFromMappingOrHook("keyForHasMany",e,t)},_addBelongsTo:function(e,t,r,n){var i=this._keyForBelongsTo(t.constructor,r);this.addBelongsTo(e,t,i,n)},_addHasMany:function(e,t,r,n){var i=this._keyForHasMany(t.constructor,r);this.addHasMany(e,t,i,n)},_keyFromMappingOrHook:function(e,t,r){var n=this.mappingOption(t,r,"key");return n?n:this[e](t,r)},registerTransform:function(e,t){this.transforms[e]=t},registerEnumTransform:function(e,t){var r={deserialize:function(e){return Ember.A(t).objectAt(e)},serialize:function(e){return Ember.EnumerableUtils.indexOf(t,e)},values:t};this.registerTransform(e,r)},map:function(e,t){this.mappings.set(e,t)},configure:function(e,t){if(e&&!t)return Ember.merge(this.globalConfigurations,e),void 0;var r,n;t.alias&&(n=t.alias,this.aliases.set(n,e),delete t.alias),r=Ember.create(this.globalConfigurations),Ember.merge(r,t),this.configurations.set(e,r)},typeFromAlias:function(e){return this._completeAliases(),this.aliases.get(e)},mappingForType:function(e){return this._reifyMappings(),this.mappings.get(e)||{}},configurationForType:function(e){return this._reifyConfigurations(),this.configurations.get(e)||this.globalConfigurations},_completeAliases:function(){this._pluralizeAliases(),this._reifyAliases()},_pluralizeAliases:function(){if(!this._didPluralizeAliases){var e,t=this.aliases,r=this.aliases.sideloadMapping,n=this;t.forEach(function(r,i){e=n.pluralize(r),t.set(e,i)}),r&&(r.forEach(function(e,r){t.set(e,r)}),delete this.aliases.sideloadMapping),this._didPluralizeAliases=!0}},_reifyAliases:function(){if(!this._didReifyAliases){var e,t=this.aliases,r=Ember.Map.create();t.forEach(function(t,n){"string"==typeof n?(e=Ember.get(Ember.lookup,n),r.set(t,e)):r.set(t,n)}),this.aliases=r,this._didReifyAliases=!0}},_reifyMappings:function(){if(!this._didReifyMappings){var e=this.mappings,t=Ember.Map.create();e.forEach(function(e,r){if("string"==typeof e){var n=Ember.get(Ember.lookup,e);t.set(n,r)}else t.set(e,r)}),this.mappings=t,this._didReifyMappings=!0}},_reifyConfigurations:function(){if(!this._didReifyConfigurations){var e=this.configurations,t=Ember.Map.create();e.forEach(function(e,r){if("string"==typeof e&&"plurals"!==e){var n=Ember.get(Ember.lookup,e);t.set(n,r)}else t.set(e,r)}),this.configurations=t,this._didReifyConfigurations=!0}},mappingOption:function(e,t,r){var n=this.mappingForType(e)[t];return n&&n[r]},configOption:function(e,t){var r=this.configurationForType(e);return r[t]},embeddedType:function(e,t){return this.mappingOption(e,t,"embedded")},eachEmbeddedRecord:function(e,t,r){this.eachEmbeddedBelongsToRecord(e,t,r),this.eachEmbeddedHasManyRecord(e,t,r)},eachEmbeddedBelongsToRecord:function(e,r,n){this.eachEmbeddedBelongsTo(e.constructor,function(i,a,o){var s=t(e,i);s&&r.call(n,s,o)})},eachEmbeddedHasManyRecord:function(e,r,n){this.eachEmbeddedHasMany(e.constructor,function(i,a,o){for(var s=t(e,i),c=0,d=t(s,"length");d>c;c++)r.call(n,s.objectAt(c),o)})},eachEmbeddedHasMany:function(e,t,r){this.eachEmbeddedRelationship(e,"hasMany",t,r)},eachEmbeddedBelongsTo:function(e,t,r){this.eachEmbeddedRelationship(e,"belongsTo",t,r)},eachEmbeddedRelationship:function(e,t,r,n){e.eachRelationship(function(i,a){var o=this.embeddedType(e,i);o&&a.kind===t&&r.call(n,i,a,o)},this)},pluralize:function(e){var t=this.configurations.get("plurals");return t&&t[e]||e+"s"},singularize:function(e){var t=this.configurations.get("plurals");if(t)for(var r in t)if(t[r]===e)return r;return e.lastIndexOf("s")===e.length-1?e.substring(0,e.length-1):e}})}(),function(){var e=Ember.isNone,t=Ember.isEmpty;DS.JSONTransforms={string:{deserialize:function(t){return e(t)?null:String(t)},serialize:function(t){return e(t)?null:String(t)}},number:{deserialize:function(e){return t(e)?null:Number(e)},serialize:function(e){return t(e)?null:Number(e)}},"boolean":{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)}},date:{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(),h=t[s],l=n(o),f=r[a];return h+", "+l+" "+f+" "+i+" "+n(c)+":"+n(d)+":"+n(u)+" GMT"}return null}}}}(),function(){var e=Ember.get;Ember.set,DS.JSONSerializer=DS.Serializer.extend({init:function(){this._super(),e(this,"transforms")||this.set("transforms",DS.JSONTransforms),this.sideloadMapping=Ember.Map.create(),this.metadataMapping=Ember.Map.create(),this.configure({meta:"meta",since:"since"})},configure:function(t,r){var n;if(t&&!r){for(n in t)this.metadataMapping.set(e(t,n),n);return this._super(t)}var i,a=r.sideloadAs;a&&(i=this.aliases.sideloadMapping||Ember.Map.create(),i.set(a,t),this.aliases.sideloadMapping=i,delete r.sideloadAs),this._super.apply(this,arguments)},addId:function(e,t,r){e[t]=r},addAttribute:function(e,t,r){e[t]=r},extractAttribute:function(e,t,r){var n=this._keyForAttributeName(e,r);return t[n]},extractId:function(e,t){var r=this._primaryKey(e);return t.hasOwnProperty(r)?t[r]+"":null},extractEmbeddedData:function(e,t){return e[t]},extractHasMany:function(e,t,r){return t[r]},extractBelongsTo:function(e,t,r){return t[r]},extractBelongsToPolymorphic:function(e,t,r){var n,i=this.keyForPolymorphicId(r),a=t[i];return a?(n=this.keyForPolymorphicType(r),{id:a,type:t[n]}):null},addBelongsTo:function(t,r,n,i){var a,o,s,c=r.constructor,d=i.key,u=null,h=i.options&&i.options.polymorphic;this.embeddedType(c,d)?((a=e(r,d))&&(u=this.serialize(a,{includeId:!0,includeType:h})),t[n]=u):(o=e(r,i.key),s=e(o,"id"),i.options&&i.options.polymorphic&&!Ember.isNone(s)?this.addBelongsToPolymorphic(t,n,s,o.constructor):t[n]=void 0===s?null:this.serializeId(s))},addBelongsToPolymorphic:function(e,t,r,n){var i=this.keyForPolymorphicId(t),a=this.keyForPolymorphicType(t);e[i]=r,e[a]=this.rootForType(n)},addHasMany:function(t,r,n,i){var a,o,s=r.constructor,c=i.key,d=[],u=i.options&&i.options.polymorphic;o=this.embeddedType(s,c),"always"===o&&(a=e(r,c),a.forEach(function(e){d.push(this.serialize(e,{includeId:!0,includeType:u}))},this),t[n]=d)},addType:function(e,t){var r=this.keyForEmbeddedType();e[r]=this.rootForType(t)},extract:function(e,t,r,n){var i=this.rootForType(r);this.sideload(e,r,t,i),this.extractMeta(e,r,t),t[i]&&(n&&e.updateId(n,t[i]),this.extractRecordRepresentation(e,r,t[i]))},extractMany:function(e,t,r,n){var i=this.rootForType(r);if(i=this.pluralize(i),this.sideload(e,r,t,i),this.extractMeta(e,r,t),t[i]){var a=t[i],o=[];n&&(n=n.toArray());for(var s=0;s