function(index, removed, added) {
    // Map the array of record objects into an array of  client ids.
    added = map(added, function(record) {
      Ember.assert("You cannot add '" + record.constructor.typeKey + "' records to this relationship (only '" + this.type.typeKey + "' allowed)", !this.type || record instanceof this.type);
      return record;
    }, this);

    this._super(index, removed, added);
  }

Overrides Ember.Array's replace method to implement

Overrides Ember . Array s replace method to implement


function(hash) {
    var owner = get(this, 'owner'),
        store = get(owner, 'store'),
        type = get(this, 'type'),
        record;

    Ember.assert("You cannot add '" + type.typeKey + "' records to this polymorphic relationship.", !get(this, 'isPolymorphic'));

    record = store.createRecord.call(store, type, hash);
    this.pushObject(record);

    return record;
  }

Create a child record within the owner

@method createRecord
@private
@param {Object} hash
@return {DS.Model} record


function(type) {
    var adapter = this.adapterFor(type);

    if (adapter && adapter.generateIdForRecord) {
      return adapter.generateIdForRecord(this);
    }

    return null;
  }

function ( type ) { var adapter = this . adapterFor ( type ) ; if ( adapter && adapter . generateIdForRecord ) { return adapter . generateIdForRecord ( this ) ; } return null ; }

If possible, this method asks the adapter to generate an ID for
a newly created record.

@method _generateId
@private
@param {String} type
@returns {String} if the adapter can generate one, an ID

If possible this method asks the adapter to generate an ID for a newly created record .


function(type, id) {
    type = this.modelFor(type);

    var record = this.recordForId(type, id);

    var promise = this.fetchRecord(record) || resolve(record, "DS: Store#findById " + type + " with id: " + id);
    return promiseObject(promise);
  }

function
(
type
,
id
)
{
type
=
this
.
modelFor
(
type
)
;
var
record
=
this
.
recordForId
(
type
,
id
)
;
var
promise
=
this
.
fetchRecord
(
record
)
||
resolve
(
record
,
"DS: Store#findById "
+
type
+
" with id: "
+
id
)
;
return
promiseObject
(
promise
)
;
}

This method returns a record for a given type and id combination.

@method findById
@private
@param {String or subclass of DS.Model} type
@param {String|Integer} id
@return {Promise} promise

This method returns a record for a given type and id combination .


function(type, ids) {
    var store = this;
    var promiseLabel = "DS: Store#findByIds " + type;
    return promiseArray(Ember.RSVP.all(map(ids, function(id) {
      return store.findById(type, id);
    })).then(Ember.A, null, "DS: Store#findByIds of " + type + " complete"));
  }

function
(
type
,
ids
)
{
var
store
=
this
;
var
promiseLabel
=
"DS: Store#findByIds "
+
type
;
return
promiseArray
(
Ember
.
RSVP
.
all
(
map
(
ids
,
function
(
id
)
{
return
store
.
findById
(
type
,
id
)
;
}
)
)
.
then
(
Ember
.
A
,
,
"DS: Store#findByIds of "
+
type
+
" complete"
)
)
;
}

This method makes a series of requests to the adapter's `find` method
and returns a promise that resolves once they are all loaded.

@private
@method findByIds
@param {String} type
@param {Array} ids
@returns {Promise} promise

This method makes a series of requests to the adapter s find method and returns a promise that resolves once they are all loaded .


function(record) {
    var type = record.constructor,
        adapter = this.adapterFor(type),
        id = get(record, 'id');

    Ember.assert("You cannot reload a record without an ID", id);
    Ember.assert("You tried to reload a record but you have no adapter (for " + type + ")", adapter);
    Ember.assert("You tried to reload a record but your adapter does not implement `find`", adapter.find);

    return _find(adapter, this, type, id);
  }

This method is called by the record's `reload` method.

This method calls the adapter's `find` method, which returns a promise. When
*that** promise resolves, `reloadRecord` will resolve the promise returned
by the record's `reload`.

@method reloadRecord
@private
@param {DS.Model} record
@return {Promise} promise

This method is called by the record s reload method .


function(records, owner, resolver) {
    if (!records.length) { return; }

    // Group By Type
    var recordsByTypeMap = Ember.MapWithDefault.create({
      defaultValue: function() { return Ember.A(); }
    });

    forEach(records, function(record) {
      recordsByTypeMap.get(record.constructor).push(record);
    });

    forEach(recordsByTypeMap, function(type, records) {
      var ids = records.mapProperty('id'),
          adapter = this.adapterFor(type);

      Ember.assert("You tried to load many records but you have no adapter (for " + type + ")", adapter);
      Ember.assert("You tried to load many records but your adapter does not implement `findMany`", adapter.findMany);

      resolver.resolve(_findMany(adapter, this, type, ids, owner));
    }, this);
  }

This method takes a list of records, groups the records by type,
converts the records into IDs, and then invokes the adapter's `findMany`
method.

The records are grouped by type to invoke `findMany` on adapters
for each unique type in records.

It is used both by a brand new relationship (via the `findMany`
method) or when the data underlying an existing relationship
changes.

@method fetchMany
@private
@param {Array} records
@param {DS.Model} owner
@param {Resolver} resolver

This method takes a list of records groups the records by type converts the records into IDs and then invokes the adapter s findMany method .


function(type, id) {
    id = coerceId(id);
    type = this.modelFor(type);
    return !!this.typeMapFor(type).idToRecord[id];
  }

function ( type , id ) { id = coerceId ( id ) ; type = this . modelFor ( type ) ; return ! ! this . typeMapFor ( type ) . idToRecord [ id ] ; }

Returns true if a record for a given type and ID is already loaded.

@method hasRecordForId
@param {String or subclass of DS.Model} type
@param {String|Integer} id
@returns {Boolean}

Returns true if a record for a given type and ID is already loaded .


function(type, id) {
    type = this.modelFor(type);

    id = coerceId(id);

    var record = this.typeMapFor(type).idToRecord[id];

    if (!record) {
      record = this.buildRecord(type, id);
    }

    return record;
  }

function ( type , id ) { type = this . modelFor ( type ) ; id = coerceId ( id ) ; var record = this . typeMapFor ( type ) . idToRecord [ id ] ; if ( ! record ) { record = this . buildRecord ( type , id ) ; } return record ; }

Returns id record for a given type and ID. If one isn't already loaded,
it builds a new record and leaves it in the `empty` state.

@method recordForId
@private
@param {String or subclass of DS.Model} type
@param {String|Integer} id
@returns {DS.Model} record

Returns id record for a given type and ID . If one isn t already loaded it builds a new record and leaves it in the empty state .


function(type, query) {
    type = this.modelFor(type);

    var array = this.recordArrayManager
      .createAdapterPopulatedRecordArray(type, query);

    var adapter = this.adapterFor(type),
        promiseLabel = "DS: Store#findQuery " + type,
        resolver = Ember.RSVP.defer(promiseLabel);

    Ember.assert("You tried to load a query but you have no adapter (for " + type + ")", adapter);
    Ember.assert("You tried to load a query but your adapter does not implement `findQuery`", adapter.findQuery);

    resolver.resolve(_findQuery(adapter, this, type, query, array));

    return promiseArray(resolver.promise);
  }

This method delegates a query to the adapter. This is the one place where
adapter-level semantics are exposed to the application.

Exposing queries this way seems preferable to creating an abstract query
language for all server-side queries, and then require all adapters to
implement them.

This method returns a promise, which is resolved with a `RecordArray`
once the server returns.

@method findQuery
@private
@param {String or subclass of DS.Model} type
@param {any} query an opaque query to be used by the adapter
@return {Promise} promise

This method delegates a query to the adapter . This is the one place where adapter - level semantics are exposed to the application .


function(type) {
    type = this.modelFor(type);

    var typeMap = this.typeMapFor(type),
        findAllCache = typeMap.findAllCache;

    if (findAllCache) { return findAllCache; }

    var array = this.recordArrayManager.createRecordArray(type);

    typeMap.findAllCache = array;
    return array;
  }

function ( type ) { type = this . modelFor ( type ) ; var typeMap = this . typeMapFor ( type ) , findAllCache = typeMap . findAllCache ; if ( findAllCache ) { return findAllCache ; } var array = this . recordArrayManager . createRecordArray ( type ) ; typeMap . findAllCache = array ; return array ; }

This method returns a filtered array that contains all of the known records
for a given type.

Note that because it's just a filter, it will have any locally
created records of the type.

Also note that multiple calls to `all` for a given type will always
return the same RecordArray.

Example

```javascript
var local_posts = store.all(App.Post);
```

@method all
@param {String or subclass of DS.Model} type
@return {DS.RecordArray}

This method returns a filtered array that contains all of the known records for a given type .


function(type) {
    type = this.modelFor(type);

    var typeMap = this.typeMapFor(type),
        records = typeMap.records, record;

    while(record = records.pop()) {
      record.unloadRecord();
    }

    typeMap.findAllCache = null;
  }

function ( type ) { type = this . modelFor ( type ) ; var typeMap = this . typeMapFor ( type ) , records = typeMap . records , record ; while ( record = records . pop ( ) ) { record . unloadRecord ( ) ; } typeMap . findAllCache = null ; }

This method unloads all of the known records for a given type.

```javascript
store.unloadAll(App.Post);
```

@method unloadAll
@param {String or subclass of DS.Model} type

This method unloads all of the known records for a given type .


function(type, query, filter) {
    var promise;

    // allow an optional server query
    if (arguments.length === 3) {
      promise = this.findQuery(type, query);
    } else if (arguments.length === 2) {
      filter = query;
    }

    type = this.modelFor(type);

    var array = this.recordArrayManager
      .createFilteredRecordArray(type, filter);
    promise = promise || resolve(array);

    return promiseArray(promise.then(function() {
      return array;
    }, null, "DS: Store#filter of " + type));
  }

function
(
type
,
query
,
filter
)
{
var
promise
;
if
(
arguments
.
length
===
3
)
{
promise
=
this
.
findQuery
(
type
,
query
)
;
}
else
if
(
arguments
.
length
===
2
)
{
filter
=
query
;
}
type
=
this
.
modelFor
(
type
)
;
var
array
=
this
.
recordArrayManager
.
createFilteredRecordArray
(
type
,
filter
)
;
promise
=
promise
||
resolve
(
array
)
;
return
promiseArray
(
promise
.
then
(
function
(
)
{
return
array
;
}
,
,
"DS: Store#filter of "
+
type
)
)
;
}

Takes a type and filter function, and returns a live RecordArray that
remains up to date as new records are loaded into the store or created
locally.

The callback function takes a materialized record, and returns true
if the record should be included in the filter and false if it should
not.

The filter function is called once on all records for the type when
it is created, and then once on each newly loaded or created record.

If any of a record's properties change, or if it changes state, the
filter function will be invoked again to determine whether it should
still be in the array.

Optionally you can pass a query which will be triggered at first. The
results returned by the server could then appear in the filter if they
match the filter function.

Example

```javascript
store.filter(App.Post, {unread: true}, function(post) {
return post.get('unread');
}).then(function(unreadPosts) {
unreadPosts.get('length'); // 5
var unreadPost = unreadPosts.objectAt(0);
unreadPosts.set('unread', false);
unreadPosts.get('length'); // 4
});
```

@method filter
@param {String or subclass of DS.Model} type
@param {Object} query optional query
@param {Function} filter
@return {DS.PromiseArray}

Takes a type and filter function and returns a live RecordArray that remains up to date as new records are loaded into the store or created locally .


function() {
    var pending = this._pendingSave.slice();
    this._pendingSave = [];

    forEach(pending, function(tuple) {
      var record = tuple[0], resolver = tuple[1],
          adapter = this.adapterFor(record.constructor),
          operation;

      if (get(record, 'isNew')) {
        operation = 'createRecord';
      } else if (get(record, 'isDeleted')) {
        operation = 'deleteRecord';
      } else {
        operation = 'updateRecord';
      }

      resolver.resolve(_commit(adapter, this, operation, record));
    }, this);
  }

function ( ) { var pending = this . _pendingSave . slice ( ) ; this . _pendingSave = [ ] ; forEach ( pending , function ( tuple ) { var record = tuple [ 0 ] , resolver = tuple [ 1 ] , adapter = this . adapterFor ( record . constructor ) , operation ; if ( get ( record , 'isNew' ) ) { operation = 'createRecord' ; } else if ( get ( record , 'isDeleted' ) ) { operation = 'deleteRecord' ; } else { operation = 'updateRecord' ; } resolver . resolve ( _commit ( adapter , this , operation , record ) ) ; } , this ) ; }

This method is called at the end of the run loop, and
flushes any records passed into `scheduleSave`

@method flushPendingSave
@private

This method is called at the end of the run loop and flushes any records passed into scheduleSave


function(record, data) {
    if (data) {
      // normalize relationship IDs into records
      data = normalizeRelationships(this, record.constructor, data, record);

      this.updateId(record, data);
    }

    record.adapterDidCommit(data);
  }

function ( record , data ) { if ( data ) { data = normalizeRelationships ( this , record . constructor , data , record ) ; this . updateId ( record , data ) ; } record . adapterDidCommit ( data ) ; }

This method is called once the promise returned by an
adapter's `createRecord`, `updateRecord` or `deleteRecord`
is resolved.

If the data provides a server-generated ID, it will
update the record and the store's indexes.

@method didSaveRecord
@private
@param {DS.Model} record the in-flight record
@param {Object} data optional data (see above)

This method is called once the promise returned by an adapter s createRecord updateRecord or deleteRecord is resolved .


function(record, data) {
    var oldId = get(record, 'id'),
        id = coerceId(data.id);

    Ember.assert("An adapter cannot assign a new id to a record that already has an id. " + record + " had id: " + oldId + " and you tried to update it with " + id + ". This likely happened because your server returned data in response to a find or update that had a different id than the one you sent.", oldId === null || id === oldId);

    this.typeMapFor(record.constructor).idToRecord[id] = record;

    set(record, 'id', id);
  }

When an adapter's `createRecord`, `updateRecord` or `deleteRecord`
resolves with data, this method extracts the ID from the supplied
data.

@method updateId
@private
@param {DS.Model} record
@param {Object} data

When an adapter s createRecord updateRecord or deleteRecord resolves with data this method extracts the ID from the supplied data .


function(type) {
    var typeMaps = get(this, 'typeMaps'),
        guid = Ember.guidFor(type),
        typeMap;

    typeMap = typeMaps[guid];

    if (typeMap) { return typeMap; }

    typeMap = {
      idToRecord: {},
      records: [],
      metadata: {}
    };

    typeMaps[guid] = typeMap;

    return typeMap;
  }

function ( type ) { var typeMaps = get ( this , 'typeMaps' ) , guid = Ember . guidFor ( type ) , typeMap ; typeMap = typeMaps [ guid ] ; if ( typeMap ) { return typeMap ; } typeMap = { idToRecord : { } , records : [ ] , metadata : { } } ; typeMaps [ guid ] = typeMap ; return typeMap ; }

Returns a map of IDs to client IDs for a given type.

@method typeMapFor
@private
@param type
@return {Object} typeMap

Returns a map of IDs to client IDs for a given type .


function(type, data, _partial) {
    // _partial is an internal param used by `update`.
    // If passed, it means that the data should be
    // merged into the existing data, not replace it.

    Ember.assert("You must include an `id` in a hash passed to `push`", data.id != null);

    type = this.modelFor(type);

    // normalize relationship IDs into records
    data = normalizeRelationships(this, type, data);

    this._load(type, data, _partial);

    return this.recordForId(type, data.id);
  }

Push some data for a given type into the store.

This method expects normalized data:

The ID is a key named `id` (an ID is mandatory)
The names of attributes are the ones you used in
your model's `DS.attr`s.
Your relationships must be:
represented as IDs or Arrays of IDs
represented as model instances
represented as URLs, under the `links` key

For this model:

```js
App.Person = DS.Model.extend({
firstName: DS.attr(),
lastName: DS.attr(),

children: DS.hasMany('person')
});
```

To represent the children as IDs:

```js
{
id: 1,
firstName: "Tom",
lastName: "Dale",
children: [1, 2, 3]
}
```

To represent the children relationship as a URL:

```js
{
id: 1,
firstName: "Tom",
lastName: "Dale",
links: {
children: "/people/1/children"
}
}
```

If you're streaming data or implementing an adapter,
make sure that you have converted the incoming data
into this form.

This method can be used both to push in brand new
records, as well as to update existing records.

@method push
@param {String or subclass of DS.Model} type
@param {Object} data
@returns {DS.Model} the record that was created or
updated.

Push some data for a given type into the store .


function (type, payload) {
    var serializer;
    if (!payload) {
      payload = type;
      serializer = defaultSerializer(this.container);
      Ember.assert("You cannot use `store#pushPayload` without a type unless your default serializer defines `pushPayload`", serializer.pushPayload);
    } else {
      serializer = this.serializerFor(type);
    }
    serializer.pushPayload(this, payload);
  }

Push some raw data into the store.

The data will be automatically deserialized using the
serializer for the `type` param.

This method can be used both to push in brand new
records, as well as to update existing records.

You can push in more than one type of object at once.
All objects should be in the format expected by the
serializer.

```js
App.ApplicationSerializer = DS.ActiveModelSerializer;

var pushData = {
posts: [
{id: 1, post_title: "Great post", comment_ids: [2]}
],
comments: [
{id: 2, comment_body: "Insightful comment"}
]
}

store.pushPayload('post', pushData);
```

@method pushPayload
@param {String} type
@param {Object} payload
@return {DS.Model} the record that was created or updated.


function(type, metadata) {
    type = this.modelFor(type);

    Ember.merge(this.typeMapFor(type).metadata, metadata);
  }

function ( type , metadata ) { type = this . modelFor ( type ) ; Ember . merge ( this . typeMapFor ( type ) . metadata , metadata ) ; }

If you have some metadata to set for a type
you can call `metaForType`.

@method metaForType
@param {String or subclass of DS.Model} type
@param {Object} metadata

If you have some metadata to set for a type you can call metaForType .


function(type, id, data) {
    var typeMap = this.typeMapFor(type),
        idToRecord = typeMap.idToRecord;

    Ember.assert('The id ' + id + ' has already been used with another record of type ' + type.toString() + '.', !id || !idToRecord[id]);

    // lookupFactory should really return an object that creates
    // instances with the injections applied
    var record = type._create({
      id: id,
      store: this,
      container: this.container
    });

    if (data) {
      record.setupData(data);
    }

    // if we're creating an item, this process will be done
    // later, once the object has been persisted.
    if (id) {
      idToRecord[id] = record;
    }

    typeMap.records.push(record);

    return record;
  }

Build a brand new record for a given type, ID, and
initial data.

@method buildRecord
@private
@param {subclass of DS.Model} type
@param {String} id
@param {Object} data
@returns {DS.Model} record

Build a brand new record for a given type ID and initial data .


function addUnsavedRecords(record, key, data) {
  if(record) {
    data.pushObjects(record.get(key).filterBy('isNew'));
  }
}

function addUnsavedRecords ( record , key , data ) { if ( record ) { data . pushObjects ( record . get ( key ) . filterBy ( 'isNew' ) ) ; } }

If there are any unsaved records that are in a hasMany they won't be in the payload, so add them back in manually.

If there are any unsaved records that are in a hasMany they won t be in the payload so add them back in manually .


function deepClone(object) {
  var clone = {}, value;

  for (var prop in object) {
    value = object[prop];
    if (value && typeof value === 'object') {
      clone[prop] = deepClone(value);
    } else {
      clone[prop] = value;
    }
  }

  return clone;
}

function deepClone ( object ) { var clone = { } , value ; for ( var prop in object ) { value = object [ prop ] ; if ( value && typeof value === 'object' ) { clone [ prop ] = deepClone ( value ) ; } else { clone [ prop ] = value ; } } return clone ; }

The created and updated states are created outside the state chart so we can reopen their substates and add mixins as necessary.

The created and updated states are created outside the state chart so we can reopen their substates and add mixins as necessary .


function(attribute, messages) {
    var wasEmpty = get(this, 'isEmpty');

    messages = this._findOrCreateMessages(attribute, messages);
    get(this, 'content').addObjects(messages);

    this.notifyPropertyChange(attribute);
    this.enumerableContentDidChange();

    if (wasEmpty && !get(this, 'isEmpty')) {
      this.trigger('becameInvalid');
    }
  }

function ( attribute , messages ) { var wasEmpty = get ( this , 'isEmpty' ) ; messages = this . _findOrCreateMessages ( attribute , messages ) ; get ( this , 'content' ) . addObjects ( messages ) ; this . notifyPropertyChange ( attribute ) ; this . enumerableContentDidChange ( ) ; if ( wasEmpty && ! get ( this , 'isEmpty' ) ) { this . trigger ( 'becameInvalid' ) ; } }

Adds error messages to a given attribute and sends
`becameInvalid` event to the record.

@method add
@param {String} attribute
@param {Array|String} messages

Adds error messages to a given attribute and sends becameInvalid event to the record .


function(attribute) {
    if (get(this, 'isEmpty')) { return; }

    var content = get(this, 'content').rejectBy('attribute', attribute);
    get(this, 'content').setObjects(content);

    this.notifyPropertyChange(attribute);
    this.enumerableContentDidChange();

    if (get(this, 'isEmpty')) {
      this.trigger('becameValid');
    }
  }

function ( attribute ) { if ( get ( this , 'isEmpty' ) ) { return ; } var content = get ( this , 'content' ) . rejectBy ( 'attribute' , attribute ) ; get ( this , 'content' ) . setObjects ( content ) ; this . notifyPropertyChange ( attribute ) ; this . enumerableContentDidChange ( ) ; if ( get ( this , 'isEmpty' ) ) { this . trigger ( 'becameValid' ) ; } }

Removes all error messages from the given attribute and sends
`becameValid` event to the record if there no more errors left.

@method remove
@param {String} attribute

Removes all error messages from the given attribute and sends becameValid event to the record if there no more errors left .


function(data) {
    set(this, 'isError', false);

    if (data) {
      this._data = data;
    } else {
      Ember.mixin(this._data, this._inFlightAttributes);
    }

    this._inFlightAttributes = {};

    this.send('didCommit');
    this.updateRecordArraysLater();

    if (!data) { return; }

    this.suspendRelationshipObservers(function() {
      this.notifyPropertyChange('data');
    });
  }

function ( data ) { set ( this , 'isError' , false ) ; if ( data ) { this . _data = data ; } else { Ember . mixin ( this . _data , this . _inFlightAttributes ) ; } this . _inFlightAttributes = { } ; this . send ( 'didCommit' ) ; this . updateRecordArraysLater ( ) ; if ( ! data ) { return ; } this . suspendRelationshipObservers ( function ( ) { this . notifyPropertyChange ( 'data' ) ; } ) ; }

If the adapter did not return a hash in response to a commit,
merge the changed attributes and relationships into the existing
saved data.

@method adapterDidCommit

If the adapter did not return a hash in response to a commit merge the changed attributes and relationships into the existing saved data .


function() {
    this._attributes = {};

    if (get(this, 'isError')) {
      this._inFlightAttributes = {};
      set(this, 'isError', false);
    }

    if (!get(this, 'isValid')) {
      this._inFlightAttributes = {};
    }

    this.send('rolledBack');

    this.suspendRelationshipObservers(function() {
      this.notifyPropertyChange('data');
    });
  }

function ( ) { this . _attributes = { } ; if ( get ( this , 'isError' ) ) { this . _inFlightAttributes = { } ; set ( this , 'isError' , false ) ; } if ( ! get ( this , 'isValid' ) ) { this . _inFlightAttributes = { } ; } this . send ( 'rolledBack' ) ; this . suspendRelationshipObservers ( function ( ) { this . notifyPropertyChange ( 'data' ) ; } ) ; }

If the model `isDirty` this function will which discard any unsaved
changes

Example

```javascript
record.get('name'); // 'Untitled Document'
record.set('name', 'Doc 1');
record.get('name'); // 'Doc 1'
record.rollback();
record.get('name'); // 'Untitled Document'
```

@method rollback

If the model isDirty this function will which discard any unsaved changes


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;
    }
  }

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 ; } }

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.

@method suspendRelationshipObservers
@private
@param callback
@param binding

The goal of this method is to temporarily disable specific observers that take action in response to application changes .


function() {
    var promiseLabel = "DS: Model#save " + this;
    var resolver = Ember.RSVP.defer(promiseLabel);

    this.get('store').scheduleSave(this, resolver);
    this._inFlightAttributes = this._attributes;
    this._attributes = {};

    return DS.PromiseObject.create({ promise: resolver.promise });
  }

function
(
)
{
var
promiseLabel
=
"DS: Model#save "
+
this
;
var
resolver
=
Ember
.
RSVP
.
defer
(
promiseLabel
)
;
this
.
get
(
'store'
)
.
scheduleSave
(
this
,
resolver
)
;
this
.
_inFlightAttributes
=
this
.
_attributes
;
this
.
_attributes
=
{
}
;
return
DS
.
PromiseObject
.
create
(
{
promise
:
resolver
.
promise
}
)
;
}

Save the record and persist any changes to the record to an
extenal source via the adapter.

Example

```javascript
record.set('name', 'Tomster');
record.save().then(function(){
Success callback
}, function() {
Error callback
});
```
@method save
@return {Promise} a promise that will be resolved when the adapter returns
successfully or rejected if the adapter returns with an error.

Save the record and persist any changes to the record to an extenal source via the adapter .


function() {
    set(this, 'isReloading', true);

    var  record = this;

    var promiseLabel = "DS: Model#reload of " + this;
    var promise = new Ember.RSVP.Promise(function(resolve){
       record.send('reloadRecord', resolve);
    }, promiseLabel).then(function() {
      record.set('isReloading', false);
      record.set('isError', false);
      return record;
    }, function(reason) {
      record.set('isError', true);
      throw reason;
    }, "DS: Model#reload complete, update flags");

    return DS.PromiseObject.create({ promise: promise });
  }

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`).

Example

```javascript
App.ModelViewRoute = Ember.Route.extend({
actions: {
reload: function() {
this.get('model').reload();
}
}
});
```

@method reload
@return {Promise} a promise that will be resolved with the record when the
adapter returns successfully or rejected if the adapter returns
with an error.


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) {
      this._data[attributeName] = value;
      this.notifyPropertyChange(attributeName);
    } else {
      this._data[attributeName] = this._inFlightAttributes[attributeName];
    }

    this.updateRecordArraysLater();
  }

function ( attributeName , value ) { if ( value !== undefined ) { this . _data [ attributeName ] = value ; this . notifyPropertyChange ( attributeName ) ; } else { this . _data [ attributeName ] = this . _inFlightAttributes [ attributeName ] ; } this . updateRecordArraysLater ( ) ; }


function(callback, binding) {
    get(this, 'attributes').forEach(function(name, meta) {
      callback.call(binding, name, meta);
    }, binding);
  }

function ( callback , binding ) { get ( this , 'attributes' ) . forEach ( function ( name , meta ) { callback . call ( binding , name , meta ) ; } , binding ) ; }

Iterates through the attributes of the model, calling the passed function on each
attribute.

The callback method you provide should have the following signature (all
parameters are optional):

```javascript
function(name, meta);
```

- `name` the name of the current property in the iteration
- `meta` the meta object for the attribute property in the iteration

Note that in addition to a callback, you can also pass an optional target
object that will be set as `this` on the context.

Example

```javascript
App.Person = DS.Model.extend({
firstName: attr('string'),
lastName: attr('string'),
birthday: attr('date')
});

App.Person.eachAttribute(function(name, meta) {
console.log(name, meta);
});

prints:
firstName {type: "string", isAttribute: true, options: Object, parentType: function, name: "firstName"}
lastName {type: "string", isAttribute: true, options: Object, parentType: function, name: "lastName"}
birthday {type: "date", isAttribute: true, options: Object, parentType: function, name: "birthday"}
```

@method eachAttribute
@param {Function} callback The callback to execute
@param {Object} [target] The target object to use
@static

Iterates through the attributes of the model calling the passed function on each attribute .


function(callback, binding) {
    get(this, 'transformedAttributes').forEach(function(name, type) {
      callback.call(binding, name, type);
    });
  }

function ( callback , binding ) { get ( this , 'transformedAttributes' ) . forEach ( function ( name , type ) { callback . call ( binding , name , type ) ; } ) ; }

Iterates through the transformedAttributes of the model, calling
the passed function on each attribute. Note the callback will not be
called for any attributes that do not have an transformation type.

The callback method you provide should have the following signature (all
parameters are optional):

```javascript
function(name, type);
```

- `name` the name of the current property in the iteration
- `type` a tring contrining the name of the type of transformed
applied to the attribute

Note that in addition to a callback, you can also pass an optional target
object that will be set as `this` on the context.

Example

```javascript
App.Person = DS.Model.extend({
firstName: attr(),
lastName: attr('string'),
birthday: attr('date')
});

App.Person.eachTransformedAttribute(function(name, type) {
console.log(name, type);
});

prints:
lastName string
birthday date
```

@method eachTransformedAttribute
@param {Function} callback The callback to execute
@param {Object} [target] The target object to use
@static

Iterates through the transformedAttributes of the model calling the passed function on each attribute . Note the callback will not be called for any attributes that do not have an transformation type .


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');
      }

      meta.parentType = proto.constructor;
    }
  }

function ( proto , key , value ) { if ( value instanceof Ember . Descriptor ) { var meta = value . meta ( ) ; if ( meta . isRelationship && meta . kind === 'belongsTo' ) { Ember . addObserver ( proto , key , null , 'belongsToDidChange' ) ; Ember . addBeforeObserver ( proto , key , null , 'belongsToWillChange' ) ; } meta . parentType = proto . constructor ; } }

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:

```javascript
DS.Model.extend({
parent: DS.belongsTo('user')
});
```

This hook would be called with "parent" as the key and the computed
property returned by `DS.belongsTo` as the value.

@method didDefineProperty
@param proto
@param key
@param value

This Ember . js hook allows an object to be notified when a property is defined .


function(callback, binding) {
    get(this, 'relationshipsByName').forEach(function(name, relationship) {
      callback.call(binding, name, relationship);
    });
  }

function ( callback , binding ) { get ( this , 'relationshipsByName' ) . forEach ( function ( name , relationship ) { callback . call ( binding , name , relationship ) ; } ) ; }

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.

@method eachRelationship
@static
@param {Function} callback the callback to invoke
@param {any} binding the value to which the callback's `this` should be bound

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 .


function() {
    forEach(this.changedRecords, function(record) {
      if (get(record, 'isDeleted')) {
        this._recordWasDeleted(record);
      } else {
        this._recordWasChanged(record);
      }
    }, this);

    this.changedRecords = [];
  }

function ( ) { forEach ( this . changedRecords , function ( record ) { if ( get ( record , 'isDeleted' ) ) { this . _recordWasDeleted ( record ) ; } else { this . _recordWasChanged ( record ) ; } } , this ) ; this . changedRecords = [ ] ; }

This method is invoked whenever data is loaded into the store by the
adapter or updated by the adapter, or when a record has changed.

It updates all record arrays that a record belongs to.

To avoid thrashing, it only runs at most once per run loop.

@method updateRecordArrays
@param {Class} type
@param {Number|String} clientId

This method is invoked whenever data is loaded into the store by the adapter or updated by the adapter or when a record has changed .


function(array, filter, type, record) {
    var shouldBeInArray;

    if (!filter) {
      shouldBeInArray = true;
    } else {
      shouldBeInArray = filter(record);
    }

    var recordArrays = this.recordArraysForRecord(record);

    if (shouldBeInArray) {
      recordArrays.add(array);
      array.addRecord(record);
    } else if (!shouldBeInArray) {
      recordArrays.remove(array);
      array.removeRecord(record);
    }
  }

function ( array , filter , type , record ) { var shouldBeInArray ; if ( ! filter ) { shouldBeInArray = true ; } else { shouldBeInArray = filter ( record ) ; } var recordArrays = this . recordArraysForRecord ( record ) ; if ( shouldBeInArray ) { recordArrays . add ( array ) ; array . addRecord ( record ) ; } else if ( ! shouldBeInArray ) { recordArrays . remove ( array ) ; array . removeRecord ( record ) ; } }

Update an individual filter.

@method updateRecordArray
@param {DS.FilteredRecordArray} array
@param {Function} filter
@param {Class} type
@param {Number|String} clientId


function(array, type, filter) {
    var typeMap = this.store.typeMapFor(type),
        records = typeMap.records, record;

    for (var i=0, l=records.length; i<l; i++) {
      record = records[i];

      if (!get(record, 'isDeleted') && !get(record, 'isEmpty')) {
        this.updateRecordArray(array, filter, type, record);
      }
    }
  }

function ( array , type , filter ) { var typeMap = this . store . typeMapFor ( type ) , records = typeMap . records , record ; for ( var i = 0 , l = records . length ; i < l ; i ++ ) { record = records [ i ] ; if ( ! get ( record , 'isDeleted' ) && ! get ( record , 'isEmpty' ) ) { this . updateRecordArray ( array , filter , type , record ) ; } } }

This method is invoked if the `filterFunction` property is
changed on a `DS.FilteredRecordArray`.

It essentially re-runs the filter from scratch. This same
method is invoked when the filter is created in th first place.

@method updateFilter
@param array
@param type
@param filter

This method is invoked if the filterFunction property is changed on a DS . FilteredRecordArray .


function(type, records) {
    var manyArray = DS.ManyArray.create({
      type: type,
      content: records,
      store: this.store
    });

    forEach(records, function(record) {
      var arrays = this.recordArraysForRecord(record);
      arrays.add(manyArray);
    }, this);

    return manyArray;
  }

function ( type , records ) { var manyArray = DS . ManyArray . create ( { type : type , content : records , store : this . store } ) ; forEach ( records , function ( record ) { var arrays = this . recordArraysForRecord ( record ) ; arrays . add ( manyArray ) ; } , this ) ; return manyArray ; }

Create a `DS.ManyArray` for a type and list of record references, and index
the `ManyArray` under each reference. This allows us to efficiently remove
records from `ManyArray`s when they are deleted.

@method createManyArray
@param {Class} type
@param {Array} references
@return {DS.ManyArray}

Create a DS . ManyArray for a type and list of record references and index the ManyArray under each reference . This allows us to efficiently remove records from ManyArray s when they are deleted .


function(type) {
    var array = DS.RecordArray.create({
      type: type,
      content: Ember.A(),
      store: this.store,
      isLoaded: true
    });

    this.registerFilteredRecordArray(array, type);

    return array;
  }

function ( type ) { var array = DS . RecordArray . create ( { type : type , content : Ember . A ( ) , store : this . store , isLoaded : true } ) ; this . registerFilteredRecordArray ( array , type ) ; return array ; }

Create a `DS.RecordArray` for a type and register it for updates.

@method createRecordArray
@param {Class} type
@return {DS.RecordArray}

Create a DS . RecordArray for a type and register it for updates .


function(type, filter) {
    var array = DS.FilteredRecordArray.create({
      type: type,
      content: Ember.A(),
      store: this.store,
      manager: this,
      filterFunction: filter
    });

    this.registerFilteredRecordArray(array, type, filter);

    return array;
  }

function ( type , filter ) { var array = DS . FilteredRecordArray . create ( { type : type , content : Ember . A ( ) , store : this . store , manager : this , filterFunction : filter } ) ; this . registerFilteredRecordArray ( array , type , filter ) ; return array ; }

Create a `DS.FilteredRecordArray` for a type and register it for updates.

@method createFilteredRecordArray
@param {Class} type
@param {Function} filter
@return {DS.FilteredRecordArray}

Create a DS . FilteredRecordArray for a type and register it for updates .


function(type, query) {
    return DS.AdapterPopulatedRecordArray.create({
      type: type,
      query: query,
      content: Ember.A(),
      store: this.store
    });
  }

function ( type , query ) { return DS . AdapterPopulatedRecordArray . create ( { type : type , query : query , content : Ember . A ( ) , store : this . store } ) ; }

Create a `DS.AdapterPopulatedRecordArray` for a type with given query.

@method createAdapterPopulatedRecordArray
@param {Class} type
@param {Object} query
@return {DS.AdapterPopulatedRecordArray}

Create a DS . AdapterPopulatedRecordArray for a type with given query .


function(array, type, filter) {
    var recordArrays = this.filteredRecordArrays.get(type);
    recordArrays.push(array);

    this.updateFilter(array, type, filter);
  }

function ( array , type , filter ) { var recordArrays = this . filteredRecordArrays . get ( type ) ; recordArrays . push ( array ) ; this . updateFilter ( array , type , filter ) ; }

Register a RecordArray for a given type to be backed by
a filter function. This will cause the array to update
automatically when records of that type change attribute
values or states.

@method registerFilteredRecordArray
@param {DS.RecordArray} array
@param {Class} type
@param {Function} filter

Register a RecordArray for a given type to be backed by a filter function . This will cause the array to update automatically when records of that type change attribute values or states .


function(record, array) {
    var loadingRecordArrays = record._loadingRecordArrays || [];
    loadingRecordArrays.push(array);
    record._loadingRecordArrays = loadingRecordArrays;
  }

function ( record , array ) { var loadingRecordArrays = record . _loadingRecordArrays || [ ] ; loadingRecordArrays . push ( array ) ; record . _loadingRecordArrays = loadingRecordArrays ; }

Internally, we maintain a map of all unloaded IDs requested by a ManyArray. As the adapter loads data into the store, the store notifies any interested ManyArrays. When the ManyArray's total number of loading records drops to zero, it becomes `isLoaded` and fires a `didLoad` event.

Internally we maintain a map of all unloaded IDs requested by a ManyArray . As the adapter loads data into the store the store notifies any interested ManyArrays . When the ManyArray s total number of loading records drops to zero it becomes isLoaded and fires a didLoad event .


function(record, options) {
    return get(record, 'store').serializerFor(record.constructor.typeKey).serialize(record, options);
  }

function ( record , options ) { return get ( record , 'store' ) . serializerFor ( record . constructor . typeKey ) . serialize ( record , options ) ; }

Proxies to the serializer's `serialize` method.

Example

```javascript
App.ApplicationAdapter = DS.Adapter.extend({
createRecord: function(store, type, record) {
var data = this.serialize(record, { includeId: true });
var url = type;

...
}
});
```

@method serialize
@param {DS.Model} record
@param {Object}   options
@return {Object} serialized record

Proxies to the serializer s serialize method .


function(store, type, ids) {
    var promises = map.call(ids, function(id) {
      return this.find(store, type, id);
    }, this);

    return Ember.RSVP.all(promises);
  }

function ( store , type , ids ) { var promises = map . call ( ids , function ( id ) { return this . find ( store , type , id ) ; } , this ) ; return Ember . RSVP . all ( promises ) ; }

Find multiple records at once.

By default, it loops over the provided ids and calls `find` on each.
May be overwritten to improve performance and reduce the number of
server requests.

Example

```javascript
App.ApplicationAdapter = DS.Adapter.extend({
findMany: function(store, type, ids) {
var url = type;
return new Ember.RSVP.Promise(function(resolve, reject) {
jQuery.getJSON(url, {ids: ids}).then(function(data) {
Ember.run(null, resolve, data);
}, function(jqXHR) {
jqXHR.then = null; // tame jQuery's ill mannered promises
Ember.run(null, reject, jqXHR);
});
});
}
});
```

@method findMany
@param {DS.Store} store
@param {subclass of DS.Model} type   the DS.Model class of the records
@param {Array}    ids
@return {Promise} promise


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 %@', [fixture]));
        }
        fixture.id = fixture.id + '';
        return fixture;
      });
    }
    return null;
  }

Implement this method in order to provide data associated with a type

@method fixturesForType
@param {Subclass of DS.Model} type
@return {Array}


function(store, type, record) {
    return store.serializerFor(type).serialize(record, { includeId: true });
  }

function ( store , type , record ) { return store . serializerFor ( type ) . serialize ( record , { includeId : true } ) ; }

Implement this method in order to provide json for CRUD methods

@method mockJSON
@param {Subclass of DS.Model} type
@param {DS.Model} record


function(type, hash, prop) {
    this.normalizeId(hash);
    this.normalizeAttributes(type, hash);
    this.normalizeRelationships(type, hash);

    this.normalizeUsingDeclaredMapping(type, hash);

    if (this.normalizeHash && this.normalizeHash[prop]) {
      this.normalizeHash[prop](hash);
    }

    return this._super(type, hash, prop);
  }

function ( type , hash , prop ) { this . normalizeId ( hash ) ; this . normalizeAttributes ( type , hash ) ; this . normalizeRelationships ( type , hash ) ; this . normalizeUsingDeclaredMapping ( type , hash ) ; if ( this . normalizeHash && this . normalizeHash [ prop ] ) { this . normalizeHash [ prop ] ( hash ) ; } return this . _super ( type , hash , prop ) ; }

If you want to do normalizations specific to some part of the payload, you
can specify those under `normalizeHash`.

For example, given the following json where the the `IDs` under
`"comments"` are provided as `_id` instead of `id`.

```javascript
{
"post": {
"id": 1,
"title": "Rails is omakase",
"comments": [ 1, 2 ]
},
"comments": [{
"_id": 1,
"body": "FIRST"
}, {
"_id": 2,
"body": "Rails is unagi"
}]
}
```

You use `normalizeHash` to normalize just the comments:

```javascript
App.PostSerializer = DS.RESTSerializer.extend({
normalizeHash: {
comments: function(hash) {
hash.id = hash._id;
delete hash._id;
return hash;
}
}
});
```

The key under `normalizeHash` is usually just the original key
that was in the original payload. However, key names will be
impacted by any modifications done in the `normalizePayload`
method. The `DS.RESTSerializer`'s default implemention makes no
changes to the payload keys.

@property normalizeHash
@type {Object}
@default undefined

Normalizes a part of the JSON payload returned by
the server. You should override this method, munge the hash
and call super if you have generic normalization to do.

It takes the type of the record that is being normalized
(as a DS.Model class), the property where the hash was
originally found, and the hash to normalize.

For example, if you have a payload that looks like this:

```js
{
"post": {
"id": 1,
"title": "Rails is omakase",
"comments": [ 1, 2 ]
},
"comments": [{
"id": 1,
"body": "FIRST"
}, {
"id": 2,
"body": "Rails is unagi"
}]
}
```

The `normalize` method will be called three times:

With `App.Post`, `"posts"` and `{ id: 1, title: "Rails is omakase", ... }`
With `App.Comment`, `"comments"` and `{ id: 1, body: "FIRST" }`
With `App.Comment`, `"comments"` and `{ id: 2, body: "Rails is unagi" }`

You can use this method, for example, to normalize underscored keys to camelized
or other general-purpose normalizations.

If you want to do normalizations specific to some part of the payload, you
can specify those under `normalizeHash`.

For example, if the `IDs` under `"comments"` are provided as `_id` instead of
`id`, you can specify how to normalize just the comments:

```js
App.PostSerializer = DS.RESTSerializer.extend({
normalizeHash: {
comments: function(hash) {
hash.id = hash._id;
delete hash._id;
return hash;
}
}
});
```

The key under `normalizeHash` is just the original key that was in the original
payload.

@method normalize
@param {subclass of DS.Model} type
@param {Object} hash
@param {String} prop
@returns {Object}

If you want to do normalizations specific to some part of the payload you can specify those under normalizeHash .


function(store, primaryType, payload, recordId, requestType) {
    payload = this.normalizePayload(primaryType, payload);

    var primaryTypeName = primaryType.typeKey,
        primaryRecord;

    for (var prop in payload) {
      var typeName  = this.typeForRoot(prop),
          isPrimary = typeName === primaryTypeName;

      // legacy support for singular resources
      if (isPrimary && Ember.typeOf(payload[prop]) !== "array" ) {
        primaryRecord = this.normalize(primaryType, payload[prop], prop);
        continue;
      }

      var type = store.modelFor(typeName);

      /*jshint loopfunc:true*/
      forEach.call(payload[prop], function(hash) {
        var typeName = this.typeForRoot(prop),
            type = store.modelFor(typeName),
            typeSerializer = store.serializerFor(type);

        hash = typeSerializer.normalize(type, hash, prop);

        var isFirstCreatedRecord = isPrimary && !recordId && !primaryRecord,
            isUpdatedRecord = isPrimary && coerceId(hash.id) === recordId;

        // find the primary record.
        //
        // It's either:
        // * the record with the same ID as the original request
        // * in the case of a newly created record that didn't have an ID, the first
        //   record in the Array
        if (isFirstCreatedRecord || isUpdatedRecord) {
          primaryRecord = hash;
        } else {
          store.push(typeName, hash);
        }
      }, this);
    }

    return primaryRecord;
  }

function ( store , primaryType , payload , recordId , requestType ) { payload = this . normalizePayload ( primaryType , payload ) ; var primaryTypeName = primaryType . typeKey , primaryRecord ; for ( var prop in payload ) { var typeName = this . typeForRoot ( prop ) , isPrimary = typeName === primaryTypeName ; if ( isPrimary && Ember . typeOf ( payload [ prop ] ) !== "array" ) { primaryRecord = this . normalize ( primaryType , payload [ prop ] , prop ) ; continue ; } var type = store . modelFor ( typeName ) ; forEach . call ( payload [ prop ] , function ( hash ) { var typeName = this . typeForRoot ( prop ) , type = store . modelFor ( typeName ) , typeSerializer = store . serializerFor ( type ) ; hash = typeSerializer . normalize ( type , hash , prop ) ; var isFirstCreatedRecord = isPrimary && ! recordId && ! primaryRecord , isUpdatedRecord = isPrimary && coerceId ( hash . id ) === recordId ; if ( isFirstCreatedRecord || isUpdatedRecord ) { primaryRecord = hash ; } else { store . push ( typeName , hash ) ; } } , this ) ; } return primaryRecord ; }

Called when the server has returned a payload representing
a single record, such as in response to a `find` or `save`.

It is your opportunity to clean up the server's response into the normalized
form expected by Ember Data.

If you want, you can just restructure the top-level of your payload, and
do more fine-grained normalization in the `normalize` method.

For example, if you have a payload like this in response to a request for
post 1:

```js
{
"id": 1,
"title": "Rails is omakase",

"_embedded": {
"comment": [{
"_id": 1,
"comment_title": "FIRST"
}, {
"_id": 2,
"comment_title": "Rails is unagi"
}]
}
}
```

You could implement a serializer that looks like this to get your payload
into shape:

```js
App.PostSerializer = DS.RESTSerializer.extend({
First, restructure the top-level so it's organized by type
extractSingle: function(store, type, payload, id, requestType) {
var comments = payload._embedded.comment;
delete payload._embedded;

payload = { comments: comments, post: payload };
return this._super(store, type, payload, id, requestType);
},

normalizeHash: {
Next, normalize individual comments, which (after `extract`)
are now located under `comments`
comments: function(hash) {
hash.id = hash._id;
hash.title = hash.comment_title;
delete hash._id;
delete hash.comment_title;
return hash;
}
}
})
```

When you call super from your own implementation of `extractSingle`, the
built-in implementation will find the primary record in your normalized
payload and push the remaining records into the store.

The primary record is the single hash found under `post` or the first
element of the `posts` array.

The primary record has special meaning when the record is being created
for the first time or updated (`createRecord` or `updateRecord`). In
particular, it will update the properties of the record that was saved.

@method extractSingle
@param {DS.Store} store
@param {subclass of DS.Model} type
@param {Object} payload
@param {String} id
@param {'find'|'createRecord'|'updateRecord'|'deleteRecord'} requestType
@returns {Object} the primary response to the original request

Called when the server has returned a payload representing a single record such as in response to a find or save .


function(store, primaryType, payload) {
    payload = this.normalizePayload(primaryType, payload);

    var primaryTypeName = primaryType.typeKey,
        primaryArray;

    for (var prop in payload) {
      var typeKey = prop,
          forcedSecondary = false;

      if (prop.charAt(0) === '_') {
        forcedSecondary = true;
        typeKey = prop.substr(1);
      }

      var typeName = this.typeForRoot(typeKey),
          type = store.modelFor(typeName),
          typeSerializer = store.serializerFor(type),
          isPrimary = (!forcedSecondary && (typeName === primaryTypeName));

      /*jshint loopfunc:true*/
      var normalizedArray = map.call(payload[prop], function(hash) {
        return typeSerializer.normalize(type, hash, prop);
      }, this);

      if (isPrimary) {
        primaryArray = normalizedArray;
      } else {
        store.pushMany(typeName, normalizedArray);
      }
    }

    return primaryArray;
  }

function ( store , primaryType , payload ) { payload = this . normalizePayload ( primaryType , payload ) ; var primaryTypeName = primaryType . typeKey , primaryArray ; for ( var prop in payload ) { var typeKey = prop , forcedSecondary = false ; if ( prop . charAt ( 0 ) === '_' ) { forcedSecondary = true ; typeKey = prop . substr ( 1 ) ; } var typeName = this . typeForRoot ( typeKey ) , type = store . modelFor ( typeName ) , typeSerializer = store . serializerFor ( type ) , isPrimary = ( ! forcedSecondary && ( typeName === primaryTypeName ) ) ; var normalizedArray = map . call ( payload [ prop ] , function ( hash ) { return typeSerializer . normalize ( type , hash , prop ) ; } , this ) ; if ( isPrimary ) { primaryArray = normalizedArray ; } else { store . pushMany ( typeName , normalizedArray ) ; } } return primaryArray ; }

Called when the server has returned a payload representing
multiple records, such as in response to a `findAll` or `findQuery`.

It is your opportunity to clean up the server's response into the normalized
form expected by Ember Data.

If you want, you can just restructure the top-level of your payload, and
do more fine-grained normalization in the `normalize` method.

For example, if you have a payload like this in response to a request for
all posts:

```js
{
"_embedded": {
"post": [{
"id": 1,
"title": "Rails is omakase"
}, {
"id": 2,
"title": "The Parley Letter"
}],
"comment": [{
"_id": 1,
"comment_title": "Rails is unagi"
"post_id": 1
}, {
"_id": 2,
"comment_title": "Don't tread on me",
"post_id": 2
}]
}
}
```

You could implement a serializer that looks like this to get your payload
into shape:

```js
App.PostSerializer = DS.RESTSerializer.extend({
First, restructure the top-level so it's organized by type
and the comments are listed under a post's `comments` key.
extractArray: function(store, type, payload, id, requestType) {
var posts = payload._embedded.post;
var comments = [];
var postCache = {};

posts.forEach(function(post) {
post.comments = [];
postCache[post.id] = post;
});

payload._embedded.comment.forEach(function(comment) {
comments.push(comment);
postCache[comment.post_id].comments.push(comment);
delete comment.post_id;
}

payload = { comments: comments, posts: payload };

return this._super(store, type, payload, id, requestType);
},

normalizeHash: {
Next, normalize individual comments, which (after `extract`)
are now located under `comments`
comments: function(hash) {
hash.id = hash._id;
hash.title = hash.comment_title;
delete hash._id;
delete hash.comment_title;
return hash;
}
}
})
```

When you call super from your own implementation of `extractArray`, the
built-in implementation will find the primary array in your normalized
payload and push the remaining records into the store.

The primary array is the array found under `posts`.

The primary record has special meaning when responding to `findQuery`
or `findHasMany`. In particular, the primary array will become the
list of records in the record array that kicked off the request.

If your primary array contains secondary (embedded) records of the same type,
you cannot place these into the primary array `posts`. Instead, place the
secondary items into an underscore prefixed property `_posts`, which will
push these items into the store and will not affect the resulting query.

@method extractArray
@param {DS.Store} store
@param {subclass of DS.Model} type
@param {Object} payload
@param {'findAll'|'findMany'|'findHasMany'|'findQuery'} requestType
@returns {Array} The primary array that was returned in response
to the original query.

Called when the server has returned a payload representing multiple records such as in response to a findAll or findQuery .


function(store, payload) {
    payload = this.normalizePayload(null, payload);

    for (var prop in payload) {
      var typeName = this.typeForRoot(prop),
          type = store.modelFor(typeName);

      /*jshint loopfunc:true*/
      var normalizedArray = map.call(Ember.makeArray(payload[prop]), function(hash) {
        return this.normalize(type, hash, prop);
      }, this);

      store.pushMany(typeName, normalizedArray);
    }
  }

function ( store , payload ) { payload = this . normalizePayload ( null , payload ) ; for ( var prop in payload ) { var typeName = this . typeForRoot ( prop ) , type = store . modelFor ( typeName ) ; var normalizedArray = map . call ( Ember . makeArray ( payload [ prop ] ) , function ( hash ) { return this . normalize ( type , hash , prop ) ; } , this ) ; store . pushMany ( typeName , normalizedArray ) ; } }

This method allows you to push a payload containing top-level
collections of records organized per type.

```js
{
"posts": [{
"id": "1",
"title": "Rails is omakase",
"author", "1",
"comments": [ "1" ]
}],
"comments": [{
"id": "1",
"body": "FIRST"
}],
"users": [{
"id": "1",
"name": "@d2h"
}]
}
```

It will first normalize the payload, so you can use this to push
in data streaming in from your server structured the same way
that fetches and saves are structured.

@method pushPayload
@param {DS.Store} store
@param {Object} payload

This method allows you to push a payload containing top - level collections of records organized per type .


function(hash, type, record, options) {
    hash[type.typeKey] = this.serialize(record, options);
  }

function ( hash , type , record , options ) { hash [ type . typeKey ] = this . serialize ( record , options ) ; }

You can use this method to customize the root keys serialized into the JSON.
By default the REST Serializer sends camelized root keys.
For example, your server may expect underscored root objects.

```js
App.ApplicationSerializer = DS.RESTSerializer.extend({
serializeIntoHash: function(data, type, record, options) {
var root = Ember.String.decamelize(type.typeKey);
data[root] = this.serialize(record, options);
}
});
```

@method serializeIntoHash
@param {Object} hash
@param {subclass of DS.Model} type
@param {DS.Model} record
@param {Object} options

You can use this method to customize the root keys serialized into the JSON . By default the REST Serializer sends camelized root keys . For example your server may expect underscored root objects .


function(record, json, relationship) {
    var key = relationship.key,
        belongsTo = get(record, key);
    key = this.keyForAttribute ? this.keyForAttribute(key) : key;
    json[key + "Type"] = belongsTo.constructor.typeKey;
  }

function ( record , json , relationship ) { var key = relationship . key , belongsTo = get ( record , key ) ; key = this . keyForAttribute ? this . keyForAttribute ( key ) : key ; json [ key + "Type" ] = belongsTo . constructor . typeKey ; }

You can use this method to customize how polymorphic objects are serialized.
By default the JSON Serializer creates the key by appending `Type` to
the attribute and value from the model's camelcased model name.

@method serializePolymorphicType
@param {DS.Model} record
@param {Object} json
@param {Object} relationship

You can use this method to customize how polymorphic objects are serialized . By default the JSON Serializer creates the key by appending Type to the attribute and value from the model s camelcased model name .


function(store, type, sinceToken) {
    var query;

    if (sinceToken) {
      query = { since: sinceToken };
    }

    return this.ajax(this.buildURL(type.typeKey), 'GET', { data: query });
  }

function ( store , type , sinceToken ) { var query ; if ( sinceToken ) { query = { since : sinceToken } ; } return this . ajax ( this . buildURL ( type . typeKey ) , 'GET' , { data : query } ) ; }

Called by the store in order to fetch a JSON array for all
of the records for a given type.

The `findAll` method makes an Ajax (HTTP GET) request to a URL computed by `buildURL`, and returns a
promise for the resulting payload.

@private
@method findAll
@param {DS.Store} store
@param {subclass of DS.Model} type
@param {String} sinceToken
@returns {Promise} promise

Called by the store in order to fetch a JSON array for all of the records for a given type .


function(store, type, ids) {
    return this.ajax(this.buildURL(type.typeKey), 'GET', { data: { ids: ids } });
  }

function ( store , type , ids ) { return this . ajax ( this . buildURL ( type . typeKey ) , 'GET' , { data : { ids : ids } } ) ; }

Called by the store in order to fetch a JSON array for
the unloaded records in a has-many relationship that were originally
specified as IDs.

For example, if the original payload looks like:

```js
{
"id": 1,
"title": "Rails is omakase",
"comments": [ 1, 2, 3 ]
}
```

The IDs will be passed as a URL-encoded Array of IDs, in this form:

```
ids[]=1&ids[]=2&ids[]=3
```

Many servers, such as Rails and PHP, will automatically convert this URL-encoded array
into an Array for you on the server-side. If you want to encode the
IDs, differently, just override this (one-line) method.

The `findMany` method makes an Ajax (HTTP GET) request to a URL computed by `buildURL`, and returns a
promise for the resulting payload.

@method findMany
@param {DS.Store} store
@param {subclass of DS.Model} type
@param {Array} ids
@returns {Promise} promise

Called by the store in order to fetch a JSON array for the unloaded records in a has - many relationship that were originally specified as IDs .


function(store, type, record) {
    var data = {};
    var serializer = store.serializerFor(type.typeKey);

    serializer.serializeIntoHash(data, type, record, { includeId: true });

    return this.ajax(this.buildURL(type.typeKey), "POST", { data: data });
  }

function ( store , type , record ) { var data = { } ; var serializer = store . serializerFor ( type . typeKey ) ; serializer . serializeIntoHash ( data , type , record , { includeId : true } ) ; return this . ajax ( this . buildURL ( type . typeKey ) , "POST" , { data : data } ) ; }

Called by the store when a newly created record is
saved via the `save` method on a model record instance.

The `createRecord` method serializes the record and makes an Ajax (HTTP POST) request
to a URL computed by `buildURL`.

See `serialize` for information on how to customize the serialized form
of a record.

@method createRecord
@param {DS.Store} store
@param {subclass of DS.Model} type
@param {DS.Model} record
@returns {Promise} promise

Called by the store when a newly created record is saved via the save method on a model record instance .


function(store, type, record) {
    var data = {};
    var serializer = store.serializerFor(type.typeKey);

    serializer.serializeIntoHash(data, type, record);

    var id = get(record, 'id');

    return this.ajax(this.buildURL(type.typeKey, id), "PUT", { data: data });
  }

function ( store , type , record ) { var data = { } ; var serializer = store . serializerFor ( type . typeKey ) ; serializer . serializeIntoHash ( data , type , record ) ; var id = get ( record , 'id' ) ; return this . ajax ( this . buildURL ( type . typeKey , id ) , "PUT" , { data : data } ) ; }

Called by the store when an existing record is saved
via the `save` method on a model record instance.

The `updateRecord` method serializes the record and makes an Ajax (HTTP PUT) request
to a URL computed by `buildURL`.

See `serialize` for information on how to customize the serialized form
of a record.

@method updateRecord
@param {DS.Store} store
@param {subclass of DS.Model} type
@param {DS.Model} record
@returns {Promise} promise

Called by the store when an existing record is saved via the save method on a model record instance .


function(store, type, record) {
    var id = get(record, 'id');

    return this.ajax(this.buildURL(type.typeKey, id), "DELETE");
  }

function ( store , type , record ) { var id = get ( record , 'id' ) ; return this . ajax ( this . buildURL ( type . typeKey , id ) , "DELETE" ) ; }

Called by the store when a record is deleted.

The `deleteRecord` method  makes an Ajax (HTTP DELETE) request to a URL computed by `buildURL`.

@method deleteRecord
@param {DS.Store} store
@param {subclass of DS.Model} type
@param {DS.Model} record
@returns {Promise} promise

Called by the store when a record is deleted .


function(type, id) {
    var url = [],
        host = get(this, 'host'),
        prefix = this.urlPrefix();

    if (type) { url.push(this.pathForType(type)); }
    if (id) { url.push(id); }

    if (prefix) { url.unshift(prefix); }

    url = url.join('/');
    if (!host && url) { url = '/' + url; }

    return url;
  }

function ( type , id ) { var url = [ ] , host = get ( this , 'host' ) , prefix = this . urlPrefix ( ) ; if ( type ) { url . push ( this . pathForType ( type ) ) ; } if ( id ) { url . push ( id ) ; } if ( prefix ) { url . unshift ( prefix ) ; } url = url . join ( '/' ) ; if ( ! host && url ) { url = '/' + url ; } return url ; }

Builds a URL for a given type and optional ID.

By default, it pluralizes the type's name (for example, 'post'
becomes 'posts' and 'person' becomes 'people'). To override the
pluralization see [pathForType](#method_pathForType).

If an ID is specified, it adds the ID to the path generated
for the type, separated by a `/`.

@method buildURL
@param {String} type
@param {String} id
@returns {String} url

Builds a URL for a given type and optional ID .


function(url, type, hash) {
    var adapter = this;

    return new Ember.RSVP.Promise(function(resolve, reject) {
      hash = adapter.ajaxOptions(url, type, hash);

      hash.success = function(json) {
        Ember.run(null, resolve, json);
      };

      hash.error = function(jqXHR, textStatus, errorThrown) {
        Ember.run(null, reject, adapter.ajaxError(jqXHR));
      };

      Ember.$.ajax(hash);
    }, "DS: RestAdapter#ajax " + type + " to " + url);
  }

function
(
url
,
type
,
hash
)
{
var
adapter
=
this
;
return
new
Ember
.
RSVP
.
Promise
(
function
(
resolve
,
reject
)
{
hash
=
adapter
.
ajaxOptions
(
url
,
type
,
hash
)
;
hash
.
success
=
function
(
json
)
{
Ember
.
run
(
,
resolve
,
json
)
;
}
;
hash
.
error
=
function
(
jqXHR
,
textStatus
,
errorThrown
)
{
Ember
.
run
(
,
reject
,
adapter
.
ajaxError
(
jqXHR
)
)
;
}
;
Ember
.
$
.
ajax
(
hash
)
;
}
,
"DS: RestAdapter#ajax "
+
type
+
" to "
+
url
)
;
}

Takes a URL, an HTTP method and a hash of data, and makes an
HTTP request.

When the server responds with a payload, Ember Data will call into `extractSingle`
or `extractArray` (depending on whether the original query was for one record or
many records).

By default, `ajax` method has the following behavior:

It sets the response `dataType` to `"json"`
If the HTTP method is not `"GET"`, it sets the `Content-Type` to be
`application/json; charset=utf-8`
If the HTTP method is not `"GET"`, it stringifies the data passed in. The
data is the serialized record in the case of a save.
Registers success and failure handlers.

@method ajax
@private
@param {String} url
@param {String} type The request type GET, POST, PUT, DELETE ect.
@param {Object} hash
@return {Promise} promise

Takes a URL an HTTP method and a hash of data and makes an HTTP request .


function Inflector(ruleSet) {
  ruleSet = ruleSet || {};
  ruleSet.uncountable = ruleSet.uncountable || {};
  ruleSet.irregularPairs = ruleSet.irregularPairs || {};

  var rules = this.rules = {
    plurals:  ruleSet.plurals || [],
    singular: ruleSet.singular || [],
    irregular: {},
    irregularInverse: {},
    uncountable: {}
  };

  loadUncountable(rules, ruleSet.uncountable);
  loadIrregular(rules, ruleSet.irregularPairs);
}

function Inflector ( ruleSet ) { ruleSet = ruleSet || { } ; ruleSet . uncountable = ruleSet . uncountable || { } ; ruleSet . irregularPairs = ruleSet . irregularPairs || { } ; var rules = this . rules = { plurals : ruleSet . plurals || [ ] , singular : ruleSet . singular || [ ] , irregular : { } , irregularInverse : { } , uncountable : { } } ; loadUncountable ( rules , ruleSet . uncountable ) ; loadIrregular ( rules , ruleSet . irregularPairs ) ; }

Inflector.Ember provides a mechanism for supplying inflection rules for your
application. Ember includes a default set of inflection rules, and provides an
API for providing additional rules.

Examples:

Creating an inflector with no rules.

```js
var inflector = new Ember.Inflector();
```

Creating an inflector with the default ember ruleset.

```js
var inflector = new Ember.Inflector(Ember.Inflector.defaultRules);

inflector.pluralize('cow') //=> 'kine'
inflector.singularize('kine') //=> 'cow'
```

Creating an inflector and adding rules later.

```javascript
var inflector = Ember.Inflector.inflector;

inflector.pluralize('advice') // => 'advices'
inflector.uncountable('advice');
inflector.pluralize('advice') // => 'advice'

inflector.pluralize('formula') // => 'formulas'
inflector.irregular('formula', 'formulae');
inflector.pluralize('formula') // => 'formulae'

you would not need to add these as they are the default rules
inflector.plural(/$/, 's');
inflector.singular(/s$/i, '');
```

Creating an inflector with a nondefault ruleset.

```javascript
var rules = {
plurals:  [ /$/, 's' ],
singular: [ /\s$/, '' ],
irregularPairs: [
[ 'cow', 'kine' ]
],
uncountable: [ 'fish' ]
};

var inflector = new Ember.Inflector(rules);
```

@class Inflector
@namespace Ember

Inflector . Ember provides a mechanism for supplying inflection rules for your application . Ember includes a default set of inflection rules and provides an API for providing additional rules .


function(key, kind) {
    key = Ember.String.decamelize(key);
    if (kind === "belongsTo") {
      return key + "_id";
    } else if (kind === "hasMany") {
      return Ember.String.singularize(key) + "_ids";
    } else {
      return key;
    }
  }

function ( key , kind ) { key = Ember . String . decamelize ( key ) ; if ( kind === "belongsTo" ) { return key + "_id" ; } else if ( kind === "hasMany" ) { return Ember . String . singularize ( key ) + "_ids" ; } else { return key ; } }

Underscores relationship names and appends "_id" or "_ids" when serializing
relationship keys.

@method keyForRelationship
@param {String} key
@param {String} kind
@returns String

Underscores relationship names and appends _id or _ids when serializing relationship keys .


function(data, type, record, options) {
    var root = Ember.String.decamelize(type.typeKey);
    data[root] = this.serialize(record, options);
  }

function ( data , type , record , options ) { var root = Ember . String . decamelize ( type . typeKey ) ; data [ root ] = this . serialize ( record , options ) ; }

Underscores the JSON root keys when serializing.

@method serializeIntoHash
@param {Object} hash
@param {subclass of DS.Model} type
@param {DS.Model} record
@param {Object} options

Underscores the JSON root keys when serializing .


function(record, json, relationship) {
    var key = relationship.key,
        belongsTo = get(record, key);
    key = this.keyForAttribute(key);
    json[key + "_type"] = Ember.String.capitalize(belongsTo.constructor.typeKey);
  }

function ( record , json , relationship ) { var key = relationship . key , belongsTo = get ( record , key ) ; key = this . keyForAttribute ( key ) ; json [ key + "_type" ] = Ember . String . capitalize ( belongsTo . constructor . typeKey ) ; }

Serializes a polymorphic type as a fully capitalized model name.

@method serializePolymorphicType
@param {DS.Model} record
@param {Object} json
@param relationship

Serializes a polymorphic type as a fully capitalized model name .


function(root) {
    var camelized = Ember.String.camelize(root);
    return Ember.String.singularize(camelized);
  }

function ( root ) { var camelized = Ember . String . camelize ( root ) ; return Ember . String . singularize ( camelized ) ; }

EXTRACT
Extracts the model typeKey from underscored root objects.

@method typeForRoot
@param {String} root
@returns String the model's typeKey

EXTRACT Extracts the model typeKey from underscored root objects .


function(data){
    if (data.links) {
      var links = data.links;

      for (var link in links) {
        var camelizedLink = Ember.String.camelize(link);

        if (camelizedLink !== link) {
          links[camelizedLink] = links[link];
          delete links[link];
        }
      }
    }
  }

function ( data ) { if ( data . links ) { var links = data . links ; for ( var link in links ) { var camelizedLink = Ember . String . camelize ( link ) ; if ( camelizedLink !== link ) { links [ camelizedLink ] = links [ link ] ; delete links [ link ] ; } } } }

Convert `snake_cased` links  to `camelCase`

@method normalizeLinks
@param {Object} hash


function(type, hash) {
    var payloadKey, payload;

    if (this.keyForRelationship) {
      type.eachRelationship(function(key, relationship) {
        if (relationship.options.polymorphic) {
          payloadKey = this.keyForAttribute(key);
          payload = hash[payloadKey];
          if (payload && payload.type) {
            payload.type = this.typeForRoot(payload.type);
          } else if (payload && relationship.kind === "hasMany") {
            var self = this;
            forEach(payload, function(single) {
              single.type = self.typeForRoot(single.type);
            });
          }
        } else {
          payloadKey = this.keyForRelationship(key, relationship.kind);
          payload = hash[payloadKey];
        }

        hash[key] = payload;

        if (key !== payloadKey) {
          delete hash[payloadKey];
        }
      }, this);
    }
  }

function ( type , hash ) { var payloadKey , payload ; if ( this . keyForRelationship ) { type . eachRelationship ( function ( key , relationship ) { if ( relationship . options . polymorphic ) { payloadKey = this . keyForAttribute ( key ) ; payload = hash [ payloadKey ] ; if ( payload && payload . type ) { payload . type = this . typeForRoot ( payload . type ) ; } else if ( payload && relationship . kind === "hasMany" ) { var self = this ; forEach ( payload , function ( single ) { single . type = self . typeForRoot ( single . type ) ; } ) ; } } else { payloadKey = this . keyForRelationship ( key , relationship . kind ) ; payload = hash [ payloadKey ] ; } hash [ key ] = payload ; if ( key !== payloadKey ) { delete hash [ payloadKey ] ; } } , this ) ; } }

Normalize the polymorphic type from the JSON.

Normalize:
```js
{
id: "1"
minion: { type: "evil_minion", id: "12"}
}
```

To:
```js
{
id: "1"
minion: { type: "evilMinion", id: "12"}
}
```

@method normalizeRelationships
@private

Normalize the polymorphic type from the JSON .


function(record, json, relationship) {
    var key   = relationship.key,
        attrs = get(this, 'attrs'),
        embed = attrs && attrs[key] && attrs[key].embedded === 'always';

    if (embed) {
      json[this.keyForAttribute(key)] = get(record, key).map(function(relation) {
        var data = relation.serialize(),
            primaryKey = get(this, 'primaryKey');

        data[primaryKey] = get(relation, primaryKey);

        return data;
      }, this);
    }
  }

function ( record , json , relationship ) { var key = relationship . key , attrs = get ( this , 'attrs' ) , embed = attrs && attrs [ key ] && attrs [ key ] . embedded === 'always' ; if ( embed ) { json [ this . keyForAttribute ( key ) ] = get ( record , key ) . map ( function ( relation ) { var data = relation . serialize ( ) , primaryKey = get ( this , 'primaryKey' ) ; data [ primaryKey ] = get ( relation , primaryKey ) ; return data ; } , this ) ; } }

Serialize has-may relationship when it is configured as embedded objects.

@method serializeHasMany

Serialize has - may relationship when it is configured as embedded objects .


function(store, primaryType, payload, recordId, requestType) {
    var root = this.keyForAttribute(primaryType.typeKey),
        partial = payload[root];

    updatePayloadWithEmbedded(store, this, primaryType, partial, payload);

    return this._super(store, primaryType, payload, recordId, requestType);
  }

function ( store , primaryType , payload , recordId , requestType ) { var root = this . keyForAttribute ( primaryType . typeKey ) , partial = payload [ root ] ; updatePayloadWithEmbedded ( store , this , primaryType , partial , payload ) ; return this . _super ( store , primaryType , payload , recordId , requestType ) ; }

Extract embedded objects out of the payload for a single object
and add them as sideloaded objects instead.

@method extractSingle

Extract embedded objects out of the payload for a single object and add them as sideloaded objects instead .


function(store, type, payload) {
    var root = this.keyForAttribute(type.typeKey),
        partials = payload[Ember.String.pluralize(root)];

    forEach(partials, function(partial) {
      updatePayloadWithEmbedded(store, this, type, partial, payload);
    }, this);

    return this._super(store, type, payload);
  }

function ( store , type , payload ) { var root = this . keyForAttribute ( type . typeKey ) , partials = payload [ Ember . String . pluralize ( root ) ] ; forEach ( partials , function ( partial ) { updatePayloadWithEmbedded ( store , this , type , partial , payload ) ; } , this ) ; return this . _super ( store , type , payload ) ; }

Extract embedded objects out of a standard payload
and add them as sideloaded objects instead.

@method extractArray

Extract embedded objects out of a standard payload and add them as sideloaded objects instead .


function(type) {
    var decamelized = Ember.String.decamelize(type);
    return Ember.String.pluralize(decamelized);
  }

function ( type ) { var decamelized = Ember . String . decamelize ( type ) ; return Ember . String . pluralize ( decamelized ) ; }

The ActiveModelAdapter overrides the `pathForType` method to build
underscored URLs by decamelizing and pluralizing the object type name.

```js
this.pathForType("famousPerson");
=> "famous_people"
```

@method pathForType
@param {String} type
@returns String

The ActiveModelAdapter overrides the pathForType method to build underscored URLs by decamelizing and pluralizing the object type name .


function(jqXHR) {
    var error = this._super(jqXHR);

    if (jqXHR && jqXHR.status === 422) {
      var jsonErrors = Ember.$.parseJSON(jqXHR.responseText)["errors"],
          errors = {};

      forEach(Ember.keys(jsonErrors), function(key) {
        errors[Ember.String.camelize(key)] = jsonErrors[key];
      });

      return new DS.InvalidError(errors);
    } else {
      return error;
    }
  }

function ( jqXHR ) { var error = this . _super ( jqXHR ) ; if ( jqXHR && jqXHR . status === 422 ) { var jsonErrors = Ember . $ . parseJSON ( jqXHR . responseText ) [ "errors" ] , errors = { } ; forEach ( Ember . keys ( jsonErrors ) , function ( key ) { errors [ Ember . String . camelize ( key ) ] = jsonErrors [ key ] ; } ) ; return new DS . InvalidError ( errors ) ; } else { return error ; } }

The ActiveModelAdapter overrides the `ajaxError` method
to return a DS.InvalidError for all 422 Unprocessable Entity
responses.

A 422 HTTP response from the server generally implies that the request
was well formed but the API was unable to process it because the
content was not semantically correct or meaningful per the API.

For more information on 422 HTTP Error code see 11.2 WebDAV RFC 4918
https://tools.ietf.org/html/rfc4918#section-11.2

@method ajaxError
@param jqXHR
@returns error

The ActiveModelAdapter overrides the ajaxError method to return a DS . InvalidError for all 422 Unprocessable Entity responses .


function parseKeyValue(/**string*/keyValue) {
  var obj = {}, key_value, key;
  forEach((keyValue || "").split('&'), function(keyValue){
    if ( keyValue ) {
      key_value = keyValue.split('=');
      key = tryDecodeURIComponent(key_value[0]);
      if ( isDefined(key) ) {
        var val = isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true;
        if (!obj[key]) {
          obj[key] = val;
        } else if(isArray(obj[key])) {
          obj[key].push(val);
        } else {
          obj[key] = [obj[key],val];
        }
      }
    }
  });
  return obj;
}

function parseKeyValue ( keyValue ) { var obj = { } , key_value , key ; forEach ( ( keyValue || "" ) . split ( '&' ) , function ( keyValue ) { if ( keyValue ) { key_value = keyValue . split ( '=' ) ; key = tryDecodeURIComponent ( key_value [ 0 ] ) ; if ( isDefined ( key ) ) { var val = isDefined ( key_value [ 1 ] ) ? tryDecodeURIComponent ( key_value [ 1 ] ) : true ; if ( ! obj [ key ] ) { obj [ key ] = val ; } else if ( isArray ( obj [ key ] ) ) { obj [ key ] . push ( val ) ; } else { obj [ key ] = [ obj [ key ] , val ] ; } } } } ) ; return obj ; }

Parses an escaped url query string into key-value pairs.
@returns Object.<(string|boolean)>

Parses an escaped url query string into key - value pairs .


function(key, value, writeAttr, attrName) {
        //special case for class attribute addition + removal
        //so that class changes can tap into the animation
        //hooks provided by the $animate service
        if(key == 'class') {
          value = value || '';
          var current = this.$$element.attr('class') || '';
          this.$removeClass(tokenDifference(current, value).join(' '));
          this.$addClass(tokenDifference(value, current).join(' '));
        } else {
          var booleanKey = getBooleanAttrName(this.$$element[0], key),
              normalizedVal,
              nodeName;

          if (booleanKey) {
            this.$$element.prop(key, value);
            attrName = booleanKey;
          }

          this[key] = value;

          // translate normalized key to actual key
          if (attrName) {
            this.$attr[key] = attrName;
          } else {
            attrName = this.$attr[key];
            if (!attrName) {
              this.$attr[key] = attrName = snake_case(key, '-');
            }
          }

          nodeName = nodeName_(this.$$element);

          // sanitize a[href] and img[src] values
          if ((nodeName === 'A' && key === 'href') ||
              (nodeName === 'IMG' && key === 'src')) {
            // NOTE: $$urlUtils.resolve() doesn't support IE < 8 so we don't sanitize for that case.
            if (!msie || msie >= 8 ) {
              normalizedVal = $$urlUtils.resolve(value);
              if (normalizedVal !== '') {
                if ((key === 'href' && !normalizedVal.match(aHrefSanitizationWhitelist)) ||
                    (key === 'src' && !normalizedVal.match(imgSrcSanitizationWhitelist))) {
                  this[key] = value = 'unsafe:' + normalizedVal;
                }
              }
            }
          }

          if (writeAttr !== false) {
            if (value === null || value === undefined) {
              this.$$element.removeAttr(attrName);
            } else {
              this.$$element.attr(attrName, value);
            }
          }
        }

        // fire observers
        var $$observers = this.$$observers;
        $$observers && forEach($$observers[key], function(fn) {
          try {
            fn(value);
          } catch (e) {
            $exceptionHandler(e);
          }
        });

        function tokenDifference(str1, str2) {
          var values = [],
              tokens1 = str1.split(/\s+/),
              tokens2 = str2.split(/\s+/);

          outer:
          for(var i=0;i<tokens1.length;i++) {
            var token = tokens1[i];
            for(var j=0;j<tokens2.length;j++) {
              if(token == tokens2[j]) continue outer;
            }
            values.push(token);
          }
          return values;
        };
      }

function
(
key
,
value
,
writeAttr
,
attrName
)
{
if
(
key
==
'class'
)
{
value
=
value
||
''
;
var
current
=
this
.
$$element
.
attr
(
'class'
)
||
''
;
this
.
$removeClass
(
tokenDifference
(
current
,
value
)
.
join
(
' '
)
)
;
this
.
$addClass
(
tokenDifference
(
value
,
current
)
.
join
(
' '
)
)
;
}
else
{
var
booleanKey
=
getBooleanAttrName
(
this
.
$$element
[
0
]
,
key
)
,
normalizedVal
,
nodeName
;
if
(
booleanKey
)
{
this
.
$$element
.
prop
(
key
,
value
)
;
attrName
=
booleanKey
;
}
this
[
key
]
=
value
;
if
(
attrName
)
{
this
.
$attr
[
key
]
=
attrName
;
}
else
{
attrName
=
this
.
$attr
[
key
]
;
if
(
!
attrName
)
{
this
.
$attr
[
key
]
=
attrName
=
snake_case
(
key
,
'-'
)
;
}
}
nodeName
=
nodeName_
(
this
.
$$element
)
;
if
(
(
nodeName
===
'A'
&&
key
===
'href'
)
||
(
nodeName
===
'IMG'
&&
key
===
'src'
)
)
{
if
(
!
msie
||
msie
>=
8
)
{
normalizedVal
=
$$urlUtils
.
resolve
(
value
)
;
if
(
normalizedVal
!==
''
)
{
if
(
(
key
===
'href'
&&
!
normalizedVal
.
match
(
aHrefSanitizationWhitelist
)
)
||
(
key
===
'src'
&&
!
normalizedVal
.
match
(
imgSrcSanitizationWhitelist
)
)
)
{
this
[
key
]
=
value
=
'unsafe:'
+
normalizedVal
;
}
}
}
}
if
(
writeAttr
!==
false
)
{
if
(
value
===
||
value
===
undefined
)
{
this
.
$$element
.
removeAttr
(
attrName
)
;
}
else
{
this
.
$$element
.
attr
(
attrName
,
value
)
;
}
}
}
var
$$observers
=
this
.
$$observers
;
$$observers
&&
forEach
(
$$observers
[
key
]
,
function
(
fn
)
{
try
{
fn
(
value
)
;
}
catch
(
e
)
{
$exceptionHandler
(
e
)
;
}
}
)
;
function
tokenDifference
(
str1
,
str2
)
{
var
values
=
[
]
,
tokens1
=
str1
.
split
(
/
\s+
/
)
,
tokens2
=
str2
.
split
(
/
\s+
/
)
;
outer
:
for
(
var
i
=
0
;
i
<
tokens1
.
length
;
i
++
)
{
var
token
=
tokens1
[
i
]
;
for
(
var
j
=
0
;
j
<
tokens2
.
length
;
j
++
)
{
if
(
token
==
tokens2
[
j
]
)
continue
outer
;
}
values
.
push
(
token
)
;
}
return
values
;
}
;
}

Set a normalized attribute on the element in a way such that all directives
can share the attribute. This function properly handles boolean attributes.
@param {string} key Normalized key. (ie ngAttribute)
@param {string|boolean} value The value to set. If `null` attribute will be deleted.
@param {boolean=} writeAttr If false, does not write the value to DOM element attribute.
Defaults to true.
@param {string=} attrName Optional none normalized name. Defaults to key.

Set a normalized attribute on the element in a way such that all directives can share the attribute . This function properly handles boolean attributes .


function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority, ignoreDirective) {
      var linkFns = [],
          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;

      for(var i = 0; i < nodeList.length; i++) {
        attrs = new Attributes();

        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.
        directives = collectDirectives(nodeList[i], [], attrs, i == 0 ? maxPriority : undefined, ignoreDirective);

        nodeLinkFn = (directives.length)
            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)
            : null;

        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes || !nodeList[i].childNodes.length)
            ? null
            : compileNodes(nodeList[i].childNodes,
                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);

        linkFns.push(nodeLinkFn);
        linkFns.push(childLinkFn);
        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);
      }

      // return a linking function if we have found anything, null otherwise
      return linkFnFound ? compositeLinkFn : null;

      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {
        var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;

        // copy nodeList so that linking doesn't break due to live list updates.
        var stableNodeList = [];
        for (i = 0, ii = nodeList.length; i < ii; i++) {
          stableNodeList.push(nodeList[i]);
        }

        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {
          node = stableNodeList[n];
          nodeLinkFn = linkFns[i++];
          childLinkFn = linkFns[i++];

          if (nodeLinkFn) {
            if (nodeLinkFn.scope) {
              childScope = scope.$new(isObject(nodeLinkFn.scope));
              jqLite(node).data('$scope', childScope);
            } else {
              childScope = scope;
            }
            childTranscludeFn = nodeLinkFn.transclude;
            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {
              nodeLinkFn(childLinkFn, childScope, node, $rootElement,
                  (function(transcludeFn) {
                    return function(cloneFn) {
                      var transcludeScope = scope.$new();
                      transcludeScope.$$transcluded = true;

                      return transcludeFn(transcludeScope, cloneFn).
                          on('$destroy', bind(transcludeScope, transcludeScope.$destroy));
                    };
                  })(childTranscludeFn || transcludeFn)
              );
            } else {
              nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);
            }
          } else if (childLinkFn) {
            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);
          }
        }
      }
    }

function compileNodes ( nodeList , transcludeFn , $rootElement , maxPriority , ignoreDirective ) { var linkFns = [ ] , nodeLinkFn , childLinkFn , directives , attrs , linkFnFound ; for ( var i = 0 ; i < nodeList . length ; i ++ ) { attrs = new Attributes ( ) ; directives = collectDirectives ( nodeList [ i ] , [ ] , attrs , i == 0 ? maxPriority : undefined , ignoreDirective ) ; nodeLinkFn = ( directives . length ) ? applyDirectivesToNode ( directives , nodeList [ i ] , attrs , transcludeFn , $rootElement ) : null ; childLinkFn = ( nodeLinkFn && nodeLinkFn . terminal || ! nodeList [ i ] . childNodes || ! nodeList [ i ] . childNodes . length ) ? null : compileNodes ( nodeList [ i ] . childNodes , nodeLinkFn ? nodeLinkFn . transclude : transcludeFn ) ; linkFns . push ( nodeLinkFn ) ; linkFns . push ( childLinkFn ) ; linkFnFound = ( linkFnFound || nodeLinkFn || childLinkFn ) ; } return linkFnFound ? compositeLinkFn : null ; function compositeLinkFn ( scope , nodeList , $rootElement , boundTranscludeFn ) { var nodeLinkFn , childLinkFn , node , childScope , childTranscludeFn , i , ii , n ; var stableNodeList = [ ] ; for ( i = 0 , ii = nodeList . length ; i < ii ; i ++ ) { stableNodeList . push ( nodeList [ i ] ) ; } for ( i = 0 , n = 0 , ii = linkFns . length ; i < ii ; n ++ ) { node = stableNodeList [ n ] ; nodeLinkFn = linkFns [ i ++ ] ; childLinkFn = linkFns [ i ++ ] ; if ( nodeLinkFn ) { if ( nodeLinkFn . scope ) { childScope = scope . $new ( isObject ( nodeLinkFn . scope ) ) ; jqLite ( node ) . data ( '$scope' , childScope ) ; } else { childScope = scope ; } childTranscludeFn = nodeLinkFn . transclude ; if ( childTranscludeFn || ( ! boundTranscludeFn && transcludeFn ) ) { nodeLinkFn ( childLinkFn , childScope , node , $rootElement , ( function ( transcludeFn ) { return function ( cloneFn ) { var transcludeScope = scope . $new ( ) ; transcludeScope . $$transcluded = true ; return transcludeFn ( transcludeScope , cloneFn ) . on ( '$destroy' , bind ( transcludeScope , transcludeScope . $destroy ) ) ; } ; } ) ( childTranscludeFn || transcludeFn ) ) ; } else { nodeLinkFn ( childLinkFn , childScope , node , undefined , boundTranscludeFn ) ; } } else if ( childLinkFn ) { childLinkFn ( scope , node . childNodes , undefined , boundTranscludeFn ) ; } } } }

Compile function matches each node in nodeList against the directives. Once all directives
for a particular node are collected their compile functions are executed. The compile
functions return values - the linking functions - are combined into a composite linking
function, which is the a linking function for the node.

@param {NodeList} nodeList an array of nodes or NodeList to compile
@param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the
scope argument is auto-generated to the new child of the transcluded parent scope.
@param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the
rootElement must be set the jqLite collection of the compile root. This is
needed so that the jqLite collection items can be replaced with widgets.
@param {number=} max directive priority
@returns {?function} A composite linking function of all of the matched directives or null.

Compile function matches each node in nodeList against the directives . Once all directives for a particular node are collected their compile functions are executed . The compile functions return values - the linking functions - are combined into a composite linking function which is the a linking function for the node .


function groupElementsLinkFnWrapper(linkFn, attrStart, attrEnd) {
      return function(scope, element, attrs, controllers) {
        element = groupScan(element[0], attrStart, attrEnd);
        return linkFn(scope, element, attrs, controllers);
      }
    }

function groupElementsLinkFnWrapper ( linkFn , attrStart , attrEnd ) { return function ( scope , element , attrs , controllers ) { element = groupScan ( element [ 0 ] , attrStart , attrEnd ) ; return linkFn ( scope , element , attrs , controllers ) ; } }

Wrapper for linking function which converts normal linking function into a grouped
linking function.
@param linkFn
@param attrStart
@param attrEnd
@returns {Function}

Wrapper for linking function which converts normal linking function into a grouped linking function .