/*!
 * @overview  Ember Data
 * @copyright Copyright 2011-2014 Tilde Inc. and contributors.
 *            Portions Copyright 2011 LivingSocial Inc.
 * @license   Licensed under MIT license (see license.js)
 * @version   1.0.0-beta.8.2a68c63a
 */
(function(global) {
var define, requireModule, require, requirejs;

(function() {
  var registry = {}, seen = {};

  define = function(name, deps, callback) {
    registry[name] = { deps: deps, callback: callback };
  };

  requirejs = require = requireModule = function(name) {
  requirejs._eak_seen = registry;

    if (seen[name]) { return seen[name]; }
    seen[name] = {};

    if (!registry[name]) {
      throw new Error("Could not find module " + name);
    }

    var mod = registry[name],
        deps = mod.deps,
        callback = mod.callback,
        reified = [],
        exports;

    for (var i=0, l=deps.length; i<l; i++) {
      if (deps[i] === 'exports') {
        reified.push(exports = {});
      } else {
        reified.push(requireModule(resolve(deps[i])));
      }
    }

    var value = callback.apply(this, reified);
    return seen[name] = exports || value;

    function resolve(child) {
      if (child.charAt(0) !== '.') { return child; }
      var parts = child.split("/");
      var parentBase = name.split("/").slice(0, -1);

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

        if (part === '..') { parentBase.pop(); }
        else if (part === '.') { continue; }
        else { parentBase.push(part); }
      }

      return parentBase.join("/");
    }
  };
})();

define("activemodel-adapter/lib/main", 
  ["./system","exports"],
  function(__dependency1__, __exports__) {
    "use strict";
    var ActiveModelAdapter = __dependency1__.ActiveModelAdapter;
    var ActiveModelSerializer = __dependency1__.ActiveModelSerializer;
    var EmbeddedRecordsMixin = __dependency1__.EmbeddedRecordsMixin;

    __exports__.ActiveModelAdapter = ActiveModelAdapter;
    __exports__.ActiveModelSerializer = ActiveModelSerializer;
    __exports__.EmbeddedRecordsMixin = EmbeddedRecordsMixin;
  });
define("activemodel-adapter/lib/setup-container", 
  ["../../ember-data/lib/system/container_proxy","./system/active_model_serializer","./system/active_model_adapter","exports"],
  function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
    "use strict";
    var ContainerProxy = __dependency1__["default"];
    var ActiveModelSerializer = __dependency2__["default"];
    var ActiveModelAdapter = __dependency3__["default"];

    __exports__["default"] = function setupActiveModelAdapter(container, application){
      var proxy = new ContainerProxy(container);
      proxy.registerDeprecations([
        {deprecated: 'serializer:_ams',  valid: 'serializer:-active-model'},
        {deprecated: 'adapter:_ams',     valid: 'adapter:-active-model'}
      ]);

      container.register('serializer:-active-model', ActiveModelSerializer);
      container.register('adapter:-active-model', ActiveModelAdapter);
    };
  });
define("activemodel-adapter/lib/system", 
  ["./system/embedded_records_mixin","./system/active_model_adapter","./system/active_model_serializer","exports"],
  function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
    "use strict";
    var EmbeddedRecordsMixin = __dependency1__["default"];
    var ActiveModelAdapter = __dependency2__["default"];
    var ActiveModelSerializer = __dependency3__["default"];

    __exports__.EmbeddedRecordsMixin = EmbeddedRecordsMixin;
    __exports__.ActiveModelAdapter = ActiveModelAdapter;
    __exports__.ActiveModelSerializer = ActiveModelSerializer;
  });
define("activemodel-adapter/lib/system/active_model_adapter", 
  ["../../../ember-data/lib/adapters","../../../ember-data/lib/system/adapter","../../../ember-inflector/lib/main","./active_model_serializer","./embedded_records_mixin","exports"],
  function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
    "use strict";
    var RESTAdapter = __dependency1__.RESTAdapter;
    var InvalidError = __dependency2__.InvalidError;
    var pluralize = __dependency3__.pluralize;
    var ActiveModelSerializer = __dependency4__["default"];
    var EmbeddedRecordsMixin = __dependency5__["default"];

    /**
      @module ember-data
    */

    var forEach = Ember.EnumerableUtils.forEach;
    var decamelize = Ember.String.decamelize,
        underscore = Ember.String.underscore;

    /**
      The ActiveModelAdapter is a subclass of the RESTAdapter designed to integrate
      with a JSON API that uses an underscored naming convention instead of camelCasing.
      It has been designed to work out of the box with the
      [active_model_serializers](http://github.com/rails-api/active_model_serializers)
      Ruby gem. This Adapter expects specific settings using ActiveModel::Serializers,
      `embed :ids, include: true` which sideloads the records.

      This adapter extends the DS.RESTAdapter by making consistent use of the camelization,
      decamelization and pluralization methods to normalize the serialized JSON into a
      format that is compatible with a conventional Rails backend and Ember Data.

      ## JSON Structure

      The ActiveModelAdapter expects the JSON returned from your server to follow
      the REST adapter conventions substituting underscored keys for camelcased ones.

      ### Conventional Names

      Attribute names in your JSON payload should be the underscored versions of
      the attributes in your Ember.js models.

      For example, if you have a `Person` model:

      ```js
      App.FamousPerson = DS.Model.extend({
        firstName: DS.attr('string'),
        lastName: DS.attr('string'),
        occupation: DS.attr('string')
      });
      ```

      The JSON returned should look like this:

      ```js
      {
        "famous_person": {
          "first_name": "Barack",
          "last_name": "Obama",
          "occupation": "President"
        }
      }
      ```

      @class ActiveModelAdapter
      @constructor
      @namespace DS
      @extends DS.RESTAdapter
    **/

    var ActiveModelAdapter = RESTAdapter.extend({
      defaultSerializer: '-active-model',
      /**
        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
        @return String
      */
      pathForType: function(type) {
        var decamelized = decamelize(type);
        var underscored = underscore(decamelized);
        return pluralize(underscored);
      },

      /**
        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
        @return error
      */
      ajaxError: function(jqXHR) {
        var error = this._super(jqXHR);

        if (jqXHR && jqXHR.status === 422) {
          var response = Ember.$.parseJSON(jqXHR.responseText),
              errors = {};

          if (response.errors !== undefined) {
            var jsonErrors = response.errors;

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

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

    __exports__["default"] = ActiveModelAdapter;
  });
define("activemodel-adapter/lib/system/active_model_serializer", 
  ["../../../ember-inflector/lib/main","../../../ember-data/lib/serializers/rest_serializer","exports"],
  function(__dependency1__, __dependency2__, __exports__) {
    "use strict";
    var singularize = __dependency1__.singularize;
    var RESTSerializer = __dependency2__["default"];
    /**
      @module ember-data
    */

    var get = Ember.get,
        forEach = Ember.EnumerableUtils.forEach,
        camelize =   Ember.String.camelize,
        capitalize = Ember.String.capitalize,
        decamelize = Ember.String.decamelize,
        underscore = Ember.String.underscore;
    /**
      The ActiveModelSerializer is a subclass of the RESTSerializer designed to integrate
      with a JSON API that uses an underscored naming convention instead of camelCasing.
      It has been designed to work out of the box with the
      [active_model_serializers](http://github.com/rails-api/active_model_serializers)
      Ruby gem. This Serializer expects specific settings using ActiveModel::Serializers,
      `embed :ids, include: true` which sideloads the records.

      This serializer extends the DS.RESTSerializer by making consistent
      use of the camelization, decamelization and pluralization methods to
      normalize the serialized JSON into a format that is compatible with
      a conventional Rails backend and Ember Data.

      ## JSON Structure

      The ActiveModelSerializer expects the JSON returned from your server
      to follow the REST adapter conventions substituting underscored keys
      for camelcased ones.

      ### Conventional Names

      Attribute names in your JSON payload should be the underscored versions of
      the attributes in your Ember.js models.

      For example, if you have a `Person` model:

      ```js
      App.FamousPerson = DS.Model.extend({
        firstName: DS.attr('string'),
        lastName: DS.attr('string'),
        occupation: DS.attr('string')
      });
      ```

      The JSON returned should look like this:

      ```js
      {
        "famous_person": {
          "first_name": "Barack",
          "last_name": "Obama",
          "occupation": "President"
        }
      }
      ```

      @class ActiveModelSerializer
      @namespace DS
      @extends DS.RESTSerializer
    */
    var ActiveModelSerializer = RESTSerializer.extend({
      // SERIALIZE

      /**
        Converts camelCased attributes to underscored when serializing.

        @method keyForAttribute
        @param {String} attribute
        @return String
      */
      keyForAttribute: function(attr) {
        return decamelize(attr);
      },

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

        @method keyForRelationship
        @param {String} key
        @param {String} kind
        @return String
      */
      keyForRelationship: function(key, kind) {
        key = decamelize(key);
        if (kind === "belongsTo") {
          return key + "_id";
        } else if (kind === "hasMany") {
          return singularize(key) + "_ids";
        } else {
          return key;
        }
      },

      /*
        Does not serialize hasMany relationships by default.
      */
      serializeHasMany: Ember.K,

      /**
        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
      */
      serializeIntoHash: function(data, type, record, options) {
        var root = underscore(decamelize(type.typeKey));
        data[root] = this.serialize(record, options);
      },

      /**
        Serializes a polymorphic type as a fully capitalized model name.

        @method serializePolymorphicType
        @param {DS.Model} record
        @param {Object} json
        @param relationship
      */
      serializePolymorphicType: function(record, json, relationship) {
        var key = relationship.key,
            belongsTo = get(record, key);

        if (belongsTo) {
          key = this.keyForAttribute(key);
          json[key + "_type"] = capitalize(belongsTo.constructor.typeKey);
        }
      },

      // EXTRACT

      /**
        Add extra step to `DS.RESTSerializer.normalize` so links are normalized.

        If your payload looks like:

        ```js
        {
          "post": {
            "id": 1,
            "title": "Rails is omakase",
            "links": { "flagged_comments": "api/comments/flagged" }
          }
        }
        ```

        The normalized version would look like this

        ```js
        {
          "post": {
            "id": 1,
            "title": "Rails is omakase",
            "links": { "flaggedComments": "api/comments/flagged" }
          }
        }
        ```

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

      normalize: function(type, hash, prop) {
        this.normalizeLinks(hash);

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

      /**
        Convert `snake_cased` links  to `camelCase`

        @method normalizeLinks
        @param {Object} data
      */

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

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

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

      /**
        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
      */
      normalizeRelationships: 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);
        }
      }
    });

    __exports__["default"] = ActiveModelSerializer;
  });
define("activemodel-adapter/lib/system/embedded_records_mixin", 
  ["../../../ember-inflector/lib/main","exports"],
  function(__dependency1__, __exports__) {
    "use strict";
    var get = Ember.get;
    var forEach = Ember.EnumerableUtils.forEach;
    var camelize = Ember.String.camelize;

    var pluralize = __dependency1__.pluralize;

    /**
      ## Using Embedded Records

      `DS.EmbeddedRecordsMixin` supports serializing embedded records.

      To set up embedded records, include the mixin when extending a serializer
      then define and configure embedded (model) relationships.

      Below is an example of a per-type serializer ('post' type).

      ```js
      App.PostSerializer = DS.ActiveModelSerializer.extend(DS.EmbeddedRecordsMixin, {
        attrs: {
          author: {embedded: 'always'},
          comments: {serialize: 'ids'}
        }
      })
      ```

      The `attrs` option for a resource `{embedded: 'always'}` is shorthand for:

      ```js
      {serialize: 'records', deserialize: 'records'}
      ```

      ### Configuring Attrs

      A resource's `attrs` option may be set to use `ids`, `records` or `no` for the
      `serialize`  and `deserialize` settings.

      The `attrs` property can be set on the ApplicationSerializer or a per-type
      serializer.

      In the case where embedded JSON is expected while extracting a payoad (reading)
      the setting is `deserialize: 'records'`, there is no need to use `ids` when
      extracting as that is the default behavior without this mixin if you are using
      the vanilla ActiveModelAdapter. Likewise, to embed JSON in the payload while
      serializing `serialize: 'records'` is the setting to use. There is an option of
      not embedding JSON in the serialized payload by using `serialize: 'ids'`. If you
      do not want the relationship sent at all, you can use `serialize: 'no'`.


      ### ActiveModelSerializer defaults
      If you do not overwrite `attrs` for a specific relationship, the `ActiveModelSerializer`
      will behave in the following way:

      BelongsTo: `{serialize:'id', deserialize:'id'}`
      HasMany:   `{serialize:no,  deserialize:'ids'}`

      ### Model Relationships

      Embedded records must have a model defined to be extracted and serialized.

      To successfully extract and serialize embedded records the model relationships
      must be setup correcty See the
      [defining relationships](/guides/models/defining-models/#toc_defining-relationships)
      section of the **Defining Models** guide page.

      Records without an `id` property are not considered embedded records, model
      instances must have an `id` property to be used with Ember Data.

      ### Example JSON payloads, Models and Serializers

      **When customizing a serializer it is imporant to grok what the cusomizations
      are, please read the docs for the methods this mixin provides, in case you need
      to modify to fit your specific needs.**

      For example review the docs for each method of this mixin:

      * [extractArray](/api/data/classes/DS.EmbeddedRecordsMixin.html#method_extractArray)
      * [extractSingle](/api/data/classes/DS.EmbeddedRecordsMixin.html#method_extractSingle)
      * [serializeBelongsTo](/api/data/classes/DS.EmbeddedRecordsMixin.html#method_serializeBelongsTo)
      * [serializeHasMany](/api/data/classes/DS.EmbeddedRecordsMixin.html#method_serializeHasMany)

      @class EmbeddedRecordsMixin
      @namespace DS
    */
    var EmbeddedRecordsMixin = Ember.Mixin.create({

      /**
        Serialize `belongsTo` relationship when it is configured as an embedded object.

        This example of an author model belongs to a post model:

        ```js
        Post = DS.Model.extend({
          title:    DS.attr('string'),
          body:     DS.attr('string'),
          author:   DS.belongsTo('author')
        });

        Author = DS.Model.extend({
          name:     DS.attr('string'),
          post:     DS.belongsTo('post')
        });
        ```

        Use a custom (type) serializer for the post model to configure embedded author

        ```js
        App.PostSerializer = DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
          attrs: {
            author: {embedded: 'always'}
          }
        })
        ```

        A payload with an attribute configured for embedded records can serialize
        the records together under the root attribute's payload:

        ```js
        {
          "post": {
            "id": "1"
            "title": "Rails is omakase",
            "author": {
              "id": "2"
              "name": "dhh"
            }
          }
        }
        ```

        @method serializeBelongsTo
        @param {DS.Model} record
        @param {Object} json
        @param {Object} relationship
      */
      serializeBelongsTo: function(record, json, relationship) {
        var attr = relationship.key;
        var attrs = this.get('attrs');
        if (noSerializeOptionSpecified(attrs, attr)) {
          this._super(record, json, relationship);
          return;
        }
        var includeIds = hasSerializeIdsOption(attrs, attr);
        var includeRecords = hasSerializeRecordsOption(attrs, attr);
        var embeddedRecord = record.get(attr);
        if (includeIds) {
          key = this.keyForRelationship(attr, relationship.kind);
          if (!embeddedRecord) {
            json[key] = null;
          } else {
            json[key] = get(embeddedRecord, 'id');
          }
        } else if (includeRecords) {
          var key = this.keyForRelationship(attr);
          if (!embeddedRecord) {
            json[key] = null;
          } else {
            json[key] = embeddedRecord.serialize({includeId: true});
            this.removeEmbeddedForeignKey(record, embeddedRecord, relationship, json[key]);
          }
        }
      },

      /**
        Serialize `hasMany` relationship when it is configured as embedded objects.

        This example of a post model has many comments:

        ```js
        Post = DS.Model.extend({
          title:    DS.attr('string'),
          body:     DS.attr('string'),
          comments: DS.hasMany('comment')
        });

        Comment = DS.Model.extend({
          body:     DS.attr('string'),
          post:     DS.belongsTo('post')
        });
        ```

        Use a custom (type) serializer for the post model to configure embedded comments

        ```js
        App.PostSerializer = DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
          attrs: {
            comments: {embedded: 'always'}
          }
        })
        ```

        A payload with an attribute configured for embedded records can serialize
        the records together under the root attribute's payload:

        ```js
        {
          "post": {
            "id": "1"
            "title": "Rails is omakase",
            "body": "I want this for my ORM, I want that for my template language..."
            "comments": [{
              "id": "1",
              "body": "Rails is unagi"
            }, {
              "id": "2",
              "body": "Omakase O_o"
            }]
          }
        }
        ```

        The attrs options object can use more specific instruction for extracting and
        serializing. When serializing, an option to embed `ids` or `records` can be set.
        When extracting the only option is `records`.

        So `{embedded: 'always'}` is shorthand for:
        `{serialize: 'records', deserialize: 'records'}`

        To embed the `ids` for a related object (using a hasMany relationship):

        ```js
        App.PostSerializer = DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
          attrs: {
            comments: {serialize: 'ids', deserialize: 'records'}
          }
        })
        ```

        ```js
        {
          "post": {
            "id": "1"
            "title": "Rails is omakase",
            "body": "I want this for my ORM, I want that for my template language..."
            "comments": ["1", "2"]
          }
        }
        ```

        @method serializeHasMany
        @param {DS.Model} record
        @param {Object} json
        @param {Object} relationship
      */
      serializeHasMany: function(record, json, relationship) {
        var attr = relationship.key;
        var attrs = this.get('attrs');
        if (noSerializeOptionSpecified(attrs, attr)) {
          this._super(record, json, relationship);
          return;
        }
        var includeIds = hasSerializeIdsOption(attrs, attr);
        var includeRecords = hasSerializeRecordsOption(attrs, attr);
        var key;
        if (includeIds) {
          key = this.keyForRelationship(attr, relationship.kind);
          json[key] = get(record, attr).mapBy('id');
        } else if (includeRecords) {
          key = this.keyForAttribute(attr);
          json[key] = get(record, attr).map(function(embeddedRecord) {
            var serializedEmbeddedRecord = embeddedRecord.serialize({includeId: true});
            this.removeEmbeddedForeignKey(record, embeddedRecord, relationship, serializedEmbeddedRecord);
            return serializedEmbeddedRecord;
          }, this);
        }
      },

      /**
        When serializing an embedded record, modify the property (in the json payload)
        that refers to the parent record (foreign key for relationship).

        Serializing a `belongsTo` relationship removes the property that refers to the
        parent record

        Serializing a `hasMany` relationship does not remove the property that refers to
        the parent record.

        @method removeEmbeddedForeignKey
        @param {DS.Model} record
        @param {DS.Model} embeddedRecord
        @param {Object} relationship
        @param {Object} json
      */
      removeEmbeddedForeignKey: function (record, embeddedRecord, relationship, json) {
        if (relationship.kind === 'hasMany') {
          return;
        } else if (relationship.kind === 'belongsTo') {
          var parentRecord = record.constructor.inverseFor(relationship.key);
          if (parentRecord) {
            var name = parentRecord.name;
            var embeddedSerializer = this.store.serializerFor(embeddedRecord.constructor);
            var parentKey = embeddedSerializer.keyForRelationship(name, parentRecord.kind);
            if (parentKey) {
              delete json[parentKey];
            }
          }
        }
      },

      /**
        Extract an embedded object from the payload for a single object
        and add the object in the compound document (side-loaded) format instead.

        A payload with an attribute configured for embedded records needs to be extracted:

        ```js
        {
          "post": {
            "id": 1
            "title": "Rails is omakase",
            "author": {
              "id": 2
              "name": "dhh"
            }
            "comments": []
          }
        }
        ```

        Ember Data is expecting a payload with a compound document (side-loaded) like:

        ```js
        {
          "post": {
            "id": "1"
            "title": "Rails is omakase",
            "author": "2"
            "comments": []
          },
          "authors": [{
            "id": "2"
            "post": "1"
            "name": "dhh"
          }]
          "comments": []
        }
        ```

        The payload's `author` attribute represents an object with a `belongsTo` relationship.
        The `post` attribute under `author` is the foreign key with the id for the post

        @method extractSingle
        @param {DS.Store} store
        @param {subclass of DS.Model} primaryType
        @param {Object} payload
        @param {String} recordId
        @return Object the primary response to the original request
      */
      extractSingle: function(store, primaryType, payload, recordId) {
        var root = this.keyForAttribute(primaryType.typeKey),
            partial = payload[root];

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

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

      /**
        Extract embedded objects in an array when an attr is configured for embedded,
        and add them as side-loaded objects instead.

        A payload with an attr configured for embedded records needs to be extracted:

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

        Ember Data is expecting a payload with compound document (side-loaded) like:

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

        The payload's `comments` attribute represents records in a `hasMany` relationship

        @method extractArray
        @param {DS.Store} store
        @param {subclass of DS.Model} primaryType
        @param {Object} payload
        @return {Array<Object>} The primary array that was returned in response
          to the original query.
      */
      extractArray: function(store, primaryType, payload) {
        var root = this.keyForAttribute(primaryType.typeKey),
            partials = payload[pluralize(root)];

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

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

    // checks config for attrs option to embedded (always) - serialize and deserialize
    function hasEmbeddedAlwaysOption(attrs, attr) {
      var option = attrsOption(attrs, attr);
      return option && option.embedded === 'always';
    }

    // checks config for attrs option to serialize ids
    function hasSerializeRecordsOption(attrs, attr) {
      var alwaysEmbed = hasEmbeddedAlwaysOption(attrs, attr);
      var option = attrsOption(attrs, attr);
      return alwaysEmbed || (option && (option.serialize === 'records'));
    }

    // checks config for attrs option to serialize records
    function hasSerializeIdsOption(attrs, attr) {
      var option = attrsOption(attrs, attr);
      return option && (option.serialize === 'ids' || option.serialize === 'id');
    }

    // checks config for attrs option to serialize records
    function noSerializeOptionSpecified(attrs, attr) {
      var option = attrsOption(attrs, attr);
      var serializeRecords = hasSerializeRecordsOption(attrs, attr);
      var serializeIds = hasSerializeIdsOption(attrs, attr);
      return !(option && (option.serialize || option.embedded));
    }

    // checks config for attrs option to deserialize records
    // a defined option object for a resource is treated the same as
    // `deserialize: 'records'`
    function hasDeserializeRecordsOption(attrs, attr) {
      var alwaysEmbed = hasEmbeddedAlwaysOption(attrs, attr);
      var option = attrsOption(attrs, attr);
      var hasSerializingOption = option && (option.deserialize || option.serialize);
      return alwaysEmbed || hasSerializingOption /* option.deserialize === 'records' */;
    }

    function attrsOption(attrs, attr) {
      return attrs && (attrs[Ember.String.camelize(attr)] || attrs[attr]);
    }

    // chooses a relationship kind to branch which function is used to update payload
    // does not change payload if attr is not embedded
    function updatePayloadWithEmbedded(serializer, store, type, payload, partial) {
      var attrs = get(serializer, 'attrs');

      if (!attrs) {
        return;
      }
      type.eachRelationship(function(key, relationship) {
        if (hasDeserializeRecordsOption(attrs, key)) {
          if (relationship.kind === "hasMany") {
            updatePayloadWithEmbeddedHasMany(serializer, store, key, relationship, payload, partial);
          }
          if (relationship.kind === "belongsTo") {
            updatePayloadWithEmbeddedBelongsTo(serializer, store, key, relationship, payload, partial);
          }
        }
      });
    }

    // handles embedding for `hasMany` relationship
    function updatePayloadWithEmbeddedHasMany(serializer, store, primaryType, relationship, payload, partial) {
      var embeddedSerializer = store.serializerFor(relationship.type.typeKey);
      var primaryKey = get(serializer, 'primaryKey');
      var attr = relationship.type.typeKey;
      // underscore forces the embedded records to be side loaded.
      // it is needed when main type === relationship.type
      var embeddedTypeKey = '_' + serializer.typeForRoot(relationship.type.typeKey);
      var expandedKey = serializer.keyForRelationship(primaryType, relationship.kind);
      var attribute  = serializer.keyForAttribute(primaryType);
      var ids = [];

      if (!partial[attribute]) {
        return;
      }

      payload[embeddedTypeKey] = payload[embeddedTypeKey] || [];

      forEach(partial[attribute], function(data) {
        var embeddedType = store.modelFor(attr);
        updatePayloadWithEmbedded(embeddedSerializer, store, embeddedType, payload, data);
        ids.push(data[primaryKey]);
        payload[embeddedTypeKey].push(data);
      });

      partial[expandedKey] = ids;
      delete partial[attribute];
    }

    // handles embedding for `belongsTo` relationship
    function updatePayloadWithEmbeddedBelongsTo(serializer, store, primaryType, relationship, payload, partial) {
      var attrs = serializer.get('attrs');

      if (!attrs ||
        !(hasDeserializeRecordsOption(attrs, Ember.String.camelize(primaryType)) ||
          hasDeserializeRecordsOption(attrs, primaryType))) {
        return;
      }
      var attr = relationship.type.typeKey;
      var _serializer = store.serializerFor(relationship.type.typeKey);
      var primaryKey = get(_serializer, 'primaryKey');
      var embeddedTypeKey = Ember.String.pluralize(attr); // TODO don't use pluralize
      var expandedKey = _serializer.keyForRelationship(primaryType, relationship.kind);
      var attribute = _serializer.keyForAttribute(primaryType);

      if (!partial[attribute]) {
        return;
      }
      payload[embeddedTypeKey] = payload[embeddedTypeKey] || [];
      var embeddedType = store.modelFor(relationship.type.typeKey);
      // Recursive call for nested record
      updatePayloadWithEmbedded(_serializer, store, embeddedType, payload, partial[attribute]);
      partial[expandedKey] = partial[attribute].id;
      // Need to move an embedded `belongsTo` object into a pluralized collection
      payload[embeddedTypeKey].push(partial[attribute]);
      // Need a reference to the parent so relationship works between both `belongsTo` records
      partial[attribute][relationship.parentType.typeKey + '_id'] = partial.id;
      delete partial[attribute];
    }

    __exports__["default"] = EmbeddedRecordsMixin;
  });
define("ember-data/lib/adapters", 
  ["./adapters/fixture_adapter","./adapters/rest_adapter","exports"],
  function(__dependency1__, __dependency2__, __exports__) {
    "use strict";
    /**
      @module ember-data
    */

    var FixtureAdapter = __dependency1__["default"];
    var RESTAdapter = __dependency2__["default"];

    __exports__.RESTAdapter = RESTAdapter;
    __exports__.FixtureAdapter = FixtureAdapter;
  });
define("ember-data/lib/adapters/fixture_adapter", 
  ["../system/adapter","exports"],
  function(__dependency1__, __exports__) {
    "use strict";
    /**
      @module ember-data
    */

    var get = Ember.get, fmt = Ember.String.fmt,
        indexOf = Ember.EnumerableUtils.indexOf;

    var counter = 0;

    var Adapter = __dependency1__["default"];

    /**
      `DS.FixtureAdapter` is an adapter that loads records from memory.
      It's primarily used for development and testing. You can also use
      `DS.FixtureAdapter` while working on the API but are not ready to
      integrate yet. It is a fully functioning adapter. All CRUD methods
      are implemented. You can also implement query logic that a remote
      system would do. It's possible to develop your entire application
      with `DS.FixtureAdapter`.

      For information on how to use the `FixtureAdapter` in your
      application please see the [FixtureAdapter
      guide](/guides/models/the-fixture-adapter/).

      @class FixtureAdapter
      @namespace DS
      @extends DS.Adapter
    */
    var FixtureAdapter = Adapter.extend({
      // by default, fixtures are already in normalized form
      serializer: null,

      /**
        If `simulateRemoteResponse` is `true` the `FixtureAdapter` will
        wait a number of milliseconds before resolving promises with the
        fixture values. The wait time can be configured via the `latency`
        property.

        @property simulateRemoteResponse
        @type {Boolean}
        @default true
      */
      simulateRemoteResponse: true,

      /**
        By default the `FixtureAdapter` will simulate a wait of the
        `latency` milliseconds before resolving promises with the fixture
        values. This behavior can be turned off via the
        `simulateRemoteResponse` property.

        @property latency
        @type {Number}
        @default 50
      */
      latency: 50,

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

        @method fixturesForType
        @param {Subclass of DS.Model} type
        @return {Array}
      */
      fixturesForType: function(type) {
        if (type.FIXTURES) {
          var fixtures = Ember.A(type.FIXTURES);
          return fixtures.map(function(fixture){
            var fixtureIdType = typeof fixture.id;
            if(fixtureIdType !== "number" && fixtureIdType !== "string"){
              throw new Error(fmt('the id property must be defined as a number or string for fixture %@', [fixture]));
            }
            fixture.id = fixture.id + '';
            return fixture;
          });
        }
        return null;
      },

      /**
        Implement this method in order to query fixtures data

        @method queryFixtures
        @param {Array} fixture
        @param {Object} query
        @param {Subclass of DS.Model} type
        @return {Promise|Array}
      */
      queryFixtures: function(fixtures, query, type) {
        Ember.assert('Not implemented: You must override the DS.FixtureAdapter::queryFixtures method to support querying the fixture store.');
      },

      /**
        @method updateFixtures
        @param {Subclass of DS.Model} type
        @param {Array} fixture
      */
      updateFixtures: function(type, fixture) {
        if(!type.FIXTURES) {
          type.FIXTURES = [];
        }

        var fixtures = type.FIXTURES;

        this.deleteLoadedFixture(type, fixture);

        fixtures.push(fixture);
      },

      /**
        Implement this method in order to provide json for CRUD methods

        @method mockJSON
        @param {Subclass of DS.Model} type
        @param {DS.Model} record
      */
      mockJSON: function(store, type, record) {
        return store.serializerFor(type).serialize(record, { includeId: true });
      },

      /**
        @method generateIdForRecord
        @param {DS.Store} store
        @param {DS.Model} record
        @return {String} id
      */
      generateIdForRecord: function(store) {
        return "fixture-" + counter++;
      },

      /**
        @method find
        @param {DS.Store} store
        @param {subclass of DS.Model} type
        @param {String} id
        @return {Promise} promise
      */
      find: function(store, type, id) {
        var fixtures = this.fixturesForType(type),
            fixture;

        Ember.assert("Unable to find fixtures for model type "+type.toString(), fixtures);

        if (fixtures) {
          fixture = Ember.A(fixtures).findProperty('id', id);
        }

        if (fixture) {
          return this.simulateRemoteCall(function() {
            return fixture;
          }, this);
        }
      },

      /**
        @method findMany
        @param {DS.Store} store
        @param {subclass of DS.Model} type
        @param {Array} ids
        @return {Promise} promise
      */
      findMany: function(store, type, ids) {
        var fixtures = this.fixturesForType(type);

        Ember.assert("Unable to find fixtures for model type "+type.toString(), fixtures);

        if (fixtures) {
          fixtures = fixtures.filter(function(item) {
            return indexOf(ids, item.id) !== -1;
          });
        }

        if (fixtures) {
          return this.simulateRemoteCall(function() {
            return fixtures;
          }, this);
        }
      },

      /**
        @private
        @method findAll
        @param {DS.Store} store
        @param {subclass of DS.Model} type
        @param {String} sinceToken
        @return {Promise} promise
      */
      findAll: function(store, type) {
        var fixtures = this.fixturesForType(type);

        Ember.assert("Unable to find fixtures for model type "+type.toString(), fixtures);

        return this.simulateRemoteCall(function() {
          return fixtures;
        }, this);
      },

      /**
        @private
        @method findQuery
        @param {DS.Store} store
        @param {subclass of DS.Model} type
        @param {Object} query
        @param {DS.AdapterPopulatedRecordArray} recordArray
        @return {Promise} promise
      */
      findQuery: function(store, type, query, array) {
        var fixtures = this.fixturesForType(type);

        Ember.assert("Unable to find fixtures for model type " + type.toString(), fixtures);

        fixtures = this.queryFixtures(fixtures, query, type);

        if (fixtures) {
          return this.simulateRemoteCall(function() {
            return fixtures;
          }, this);
        }
      },

      /**
        @method createRecord
        @param {DS.Store} store
        @param {subclass of DS.Model} type
        @param {DS.Model} record
        @return {Promise} promise
      */
      createRecord: function(store, type, record) {
        var fixture = this.mockJSON(store, type, record);

        this.updateFixtures(type, fixture);

        return this.simulateRemoteCall(function() {
          return fixture;
        }, this);
      },

      /**
        @method updateRecord
        @param {DS.Store} store
        @param {subclass of DS.Model} type
        @param {DS.Model} record
        @return {Promise} promise
      */
      updateRecord: function(store, type, record) {
        var fixture = this.mockJSON(store, type, record);

        this.updateFixtures(type, fixture);

        return this.simulateRemoteCall(function() {
          return fixture;
        }, this);
      },

      /**
        @method deleteRecord
        @param {DS.Store} store
        @param {subclass of DS.Model} type
        @param {DS.Model} record
        @return {Promise} promise
      */
      deleteRecord: function(store, type, record) {
        var fixture = this.mockJSON(store, type, record);

        this.deleteLoadedFixture(type, fixture);

        return this.simulateRemoteCall(function() {
          // no payload in a deletion
          return null;
        });
      },

      /*
        @method deleteLoadedFixture
        @private
        @param type
        @param record
      */
      deleteLoadedFixture: function(type, record) {
        var existingFixture = this.findExistingFixture(type, record);

        if(existingFixture) {
          var index = indexOf(type.FIXTURES, existingFixture);
          type.FIXTURES.splice(index, 1);
          return true;
        }
      },

      /*
        @method findExistingFixture
        @private
        @param type
        @param record
      */
      findExistingFixture: function(type, record) {
        var fixtures = this.fixturesForType(type);
        var id = get(record, 'id');

        return this.findFixtureById(fixtures, id);
      },

      /*
        @method findFixtureById
        @private
        @param fixtures
        @param id
      */
      findFixtureById: function(fixtures, id) {
        return Ember.A(fixtures).find(function(r) {
          if(''+get(r, 'id') === ''+id) {
            return true;
          } else {
            return false;
          }
        });
      },

      /*
        @method simulateRemoteCall
        @private
        @param callback
        @param context
      */
      simulateRemoteCall: function(callback, context) {
        var adapter = this;

        return new Ember.RSVP.Promise(function(resolve) {
          if (get(adapter, 'simulateRemoteResponse')) {
            // Schedule with setTimeout
            Ember.run.later(function() {
              resolve(callback.call(context));
            }, get(adapter, 'latency'));
          } else {
            // Asynchronous, but at the of the runloop with zero latency
            Ember.run.schedule('actions', null, function() {
              resolve(callback.call(context));
            });
          }
        }, "DS: FixtureAdapter#simulateRemoteCall");
      }
    });

    __exports__["default"] = FixtureAdapter;
  });
define("ember-data/lib/adapters/rest_adapter", 
  ["../system/adapter","exports"],
  function(__dependency1__, __exports__) {
    "use strict";
    /**
      @module ember-data
    */

    var Adapter = __dependency1__["default"];
    var get = Ember.get, set = Ember.set;
    var forEach = Ember.ArrayPolyfills.forEach;

    /**
      The REST adapter allows your store to communicate with an HTTP server by
      transmitting JSON via XHR. Most Ember.js apps that consume a JSON API
      should use the REST adapter.

      This adapter is designed around the idea that the JSON exchanged with
      the server should be conventional.

      ## JSON Structure

      The REST adapter expects the JSON returned from your server to follow
      these conventions.

      ### Object Root

      The JSON payload should be an object that contains the record inside a
      root property. For example, in response to a `GET` request for
      `/posts/1`, the JSON should look like this:

      ```js
      {
        "post": {
          "title": "I'm Running to Reform the W3C's Tag",
          "author": "Yehuda Katz"
        }
      }
      ```

      ### Conventional Names

      Attribute names in your JSON payload should be the camelCased versions of
      the attributes in your Ember.js models.

      For example, if you have a `Person` model:

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

      The JSON returned should look like this:

      ```js
      {
        "person": {
          "firstName": "Barack",
          "lastName": "Obama",
          "occupation": "President"
        }
      }
      ```

      ## Customization

      ### Endpoint path customization

      Endpoint paths can be prefixed with a `namespace` by setting the namespace
      property on the adapter:

      ```js
      DS.RESTAdapter.reopen({
        namespace: 'api/1'
      });
      ```
      Requests for `App.Person` would now target `/api/1/people/1`.

      ### Host customization

      An adapter can target other hosts by setting the `host` property.

      ```js
      DS.RESTAdapter.reopen({
        host: 'https://api.example.com'
      });
      ```

      ### Headers customization

      Some APIs require HTTP headers, e.g. to provide an API key. Arbitrary
      headers can be set as key/value pairs on the `RESTAdapter`'s `headers`
      object and Ember Data will send them along with each ajax request.


      ```js
      App.ApplicationAdapter = DS.RESTAdapter.extend({
        headers: {
          "API_KEY": "secret key",
          "ANOTHER_HEADER": "Some header value"
        }
      });
      ```

      `headers` can also be used as a computed property to support dynamic
      headers. In the example below, the `session` object has been
      injected into an adapter by Ember's container.

      ```js
      App.ApplicationAdapter = DS.RESTAdapter.extend({
        headers: function() {
          return {
            "API_KEY": this.get("session.authToken"),
            "ANOTHER_HEADER": "Some header value"
          };
        }.property("session.authToken")
      });
      ```

      In some cases, your dynamic headers may require data from some
      object outside of Ember's observer system (for example
      `document.cookie`). You can use the
      [volatile](/api/classes/Ember.ComputedProperty.html#method_volatile)
      function to set the property into a non-chached mode causing the headers to
      be recomputed with every request.

      ```js
      App.ApplicationAdapter = DS.RESTAdapter.extend({
        headers: function() {
          return {
            "API_KEY": Ember.get(document.cookie.match(/apiKey\=([^;]*)/), "1"),
            "ANOTHER_HEADER": "Some header value"
          };
        }.property().volatile();
      });
      ```

      @class RESTAdapter
      @constructor
      @namespace DS
      @extends DS.Adapter
    */
    var RESTAdapter = Adapter.extend({
      defaultSerializer: '-rest',
      /**
        Endpoint paths can be prefixed with a `namespace` by setting the namespace
        property on the adapter:

        ```javascript
        DS.RESTAdapter.reopen({
          namespace: 'api/1'
        });
        ```

        Requests for `App.Post` would now target `/api/1/post/`.

        @property namespace
        @type {String}
      */

      /**
        An adapter can target other hosts by setting the `host` property.

        ```javascript
        DS.RESTAdapter.reopen({
          host: 'https://api.example.com'
        });
        ```

        Requests for `App.Post` would now target `https://api.example.com/post/`.

        @property host
        @type {String}
      */

      /**
        Some APIs require HTTP headers, e.g. to provide an API
        key. Arbitrary headers can be set as key/value pairs on the
        `RESTAdapter`'s `headers` object and Ember Data will send them
        along with each ajax request. For dynamic headers see [headers
        customization](/api/data/classes/DS.RESTAdapter.html#toc_headers-customization).

        ```javascript
        App.ApplicationAdapter = DS.RESTAdapter.extend({
          headers: {
            "API_KEY": "secret key",
            "ANOTHER_HEADER": "Some header value"
          }
        });
        ```

        @property headers
        @type {Object}
      */

      /**
        Called by the store in order to fetch the JSON for a given
        type and ID.

        The `find` method makes an Ajax request to a URL computed by `buildURL`, and returns a
        promise for the resulting payload.

        This method performs an HTTP `GET` request with the id provided as part of the query string.

        @method find
        @param {DS.Store} store
        @param {subclass of DS.Model} type
        @param {String} id
        @return {Promise} promise
      */
      find: function(store, type, id) {
        return this.ajax(this.buildURL(type.typeKey, id), 'GET');
      },

      /**
        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
        @return {Promise} promise
      */
      findAll: 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
        the records that match a particular query.

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

        The `query` argument is a simple JavaScript object that will be passed directly
        to the server as parameters.

        @private
        @method findQuery
        @param {DS.Store} store
        @param {subclass of DS.Model} type
        @param {Object} query
        @return {Promise} promise
      */
      findQuery: function(store, type, query) {
        return this.ajax(this.buildURL(type.typeKey), 'GET', { data: query });
      },

      /**
        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
        @return {Promise} promise
      */
      findMany: 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 a URL (inside of `links`).

        For example, if your original payload looks like this:

        ```js
        {
          "post": {
            "id": 1,
            "title": "Rails is omakase",
            "links": { "comments": "/posts/1/comments" }
          }
        }
        ```

        This method will be called with the parent record and `/posts/1/comments`.

        The `findHasMany` method will make an Ajax (HTTP GET) request to the originally specified URL.
        If the URL is host-relative (starting with a single slash), the
        request will use the host specified on the adapter (if any).

        @method findHasMany
        @param {DS.Store} store
        @param {DS.Model} record
        @param {String} url
        @return {Promise} promise
      */
      findHasMany: function(store, record, url) {
        var host = get(this, 'host'),
            id   = get(record, 'id'),
            type = record.constructor.typeKey;

        if (host && url.charAt(0) === '/' && url.charAt(1) !== '/') {
          url = host + url;
        }

        return this.ajax(this.urlPrefix(url, this.buildURL(type, id)), 'GET');
      },

      /**
        Called by the store in order to fetch a JSON array for
        the unloaded records in a belongs-to relationship that were originally
        specified as a URL (inside of `links`).

        For example, if your original payload looks like this:

        ```js
        {
          "person": {
            "id": 1,
            "name": "Tom Dale",
            "links": { "group": "/people/1/group" }
          }
        }
        ```

        This method will be called with the parent record and `/people/1/group`.

        The `findBelongsTo` method will make an Ajax (HTTP GET) request to the originally specified URL.

        @method findBelongsTo
        @param {DS.Store} store
        @param {DS.Model} record
        @param {String} url
        @return {Promise} promise
      */
      findBelongsTo: function(store, record, url) {
        var id   = get(record, 'id'),
            type = record.constructor.typeKey;

        return this.ajax(this.urlPrefix(url, this.buildURL(type, id)), 'GET');
      },

      /**
        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
        @return {Promise} promise
      */
      createRecord: 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 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
        @return {Promise} promise
      */
      updateRecord: 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 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
        @return {Promise} promise
      */
      deleteRecord: function(store, type, record) {
        var id = get(record, 'id');

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

      /**
        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
        @return {String} url
      */
      buildURL: 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;
      },

      /**
        @method urlPrefix
        @private
        @param {String} path
        @param {String} parentUrl
        @return {String} urlPrefix
      */
      urlPrefix: function(path, parentURL) {
        var host = get(this, 'host'),
            namespace = get(this, 'namespace'),
            url = [];

        if (path) {
          // Absolute path
          if (path.charAt(0) === '/') {
            if (host) {
              path = path.slice(1);
              url.push(host);
            }
          // Relative path
          } else if (!/^http(s)?:\/\//.test(path)) {
            url.push(parentURL);
          }
        } else {
          if (host) { url.push(host); }
          if (namespace) { url.push(namespace); }
        }

        if (path) {
          url.push(path);
        }

        return url.join('/');
      },

      /**
        Determines the pathname for a given type.

        By default, it pluralizes the type's name (for example,
        'post' becomes 'posts' and 'person' becomes 'people').

        ### Pathname customization

        For example if you have an object LineItem with an
        endpoint of "/line_items/".

        ```js
        App.ApplicationAdapter = DS.RESTAdapter.extend({
          pathForType: function(type) {
            var decamelized = Ember.String.decamelize(type);
            return Ember.String.pluralize(decamelized);
          }
        });
        ```

        @method pathForType
        @param {String} type
        @return {String} path
      **/
      pathForType: function(type) {
        var camelized = Ember.String.camelize(type);
        return Ember.String.pluralize(camelized);
      },

      /**
        Takes an ajax response, and returns a relevant error.

        Returning a `DS.InvalidError` from this method will cause the
        record to transition into the `invalid` state and make the
        `errors` object available on the record.

        ```javascript
        App.ApplicationAdapter = DS.RESTAdapter.extend({
          ajaxError: function(jqXHR) {
            var error = this._super(jqXHR);

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

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

        Note: As a correctness optimization, the default implementation of
        the `ajaxError` method strips out the `then` method from jquery's
        ajax response (jqXHR). This is important because the jqXHR's
        `then` method fulfills the promise with itself resulting in a
        circular "thenable" chain which may cause problems for some
        promise libraries.

        @method ajaxError
        @param  {Object} jqXHR
        @return {Object} jqXHR
      */
      ajaxError: function(jqXHR) {
        if (jqXHR && typeof jqXHR === 'object') {
          jqXHR.then = null;
        }

        return jqXHR;
      },

      /**
        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 etc.
        @param {Object} hash
        @return {Promise} promise
      */
      ajax: 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);
      },

      /**
        @method ajaxOptions
        @private
        @param {String} url
        @param {String} type The request type GET, POST, PUT, DELETE etc.
        @param {Object} hash
        @return {Object} hash
      */
      ajaxOptions: function(url, type, hash) {
        hash = hash || {};
        hash.url = url;
        hash.type = type;
        hash.dataType = 'json';
        hash.context = this;

        if (hash.data && type !== 'GET') {
          hash.contentType = 'application/json; charset=utf-8';
          hash.data = JSON.stringify(hash.data);
        }

        var headers = get(this, 'headers');
        if (headers !== undefined) {
          hash.beforeSend = function (xhr) {
            forEach.call(Ember.keys(headers), function(key) {
              xhr.setRequestHeader(key, headers[key]);
            });
          };
        }


        return hash;
      }

    });

    __exports__["default"] = RESTAdapter;
  });
define("ember-data/lib/core", 
  ["exports"],
  function(__exports__) {
    "use strict";
    /**
      @module ember-data
    */

    /**
      All Ember Data methods and functions are defined inside of this namespace.

      @class DS
      @static
    */
    var DS;
    if ('undefined' === typeof DS) {
      /**
        @property VERSION
        @type String
        @default '1.0.0-beta.8.2a68c63a'
        @static
      */
      DS = Ember.Namespace.create({
        VERSION: '1.0.0-beta.8.2a68c63a'
      });

      if (Ember.libraries) {
        Ember.libraries.registerCoreLibrary('Ember Data', DS.VERSION);
      }
    }

    __exports__["default"] = DS;
  });
define("ember-data/lib/ember-initializer", 
  ["./setup-container"],
  function(__dependency1__) {
    "use strict";
    var setupContainer = __dependency1__["default"];

    var K = Ember.K;

    /**
      @module ember-data
    */

    /**

      This code initializes Ember-Data onto an Ember application.

      If an Ember.js developer defines a subclass of DS.Store on their application,
      as `App.ApplicationStore` (or via a module system that resolves to `store:application`)
      this code will automatically instantiate it and make it available on the
      router.

      Additionally, after an application's controllers have been injected, they will
      each have the store made available to them.

      For example, imagine an Ember.js application with the following classes:

      App.ApplicationStore = DS.Store.extend({
        adapter: 'custom'
      });

      App.PostsController = Ember.ArrayController.extend({
        // ...
      });

      When the application is initialized, `App.ApplicationStore` will automatically be
      instantiated, and the instance of `App.PostsController` will have its `store`
      property set to that instance.

      Note that this code will only be run if the `ember-application` package is
      loaded. If Ember Data is being used in an environment other than a
      typical application (e.g., node.js where only `ember-runtime` is available),
      this code will be ignored.
    */

    Ember.onLoad('Ember.Application', function(Application) {

      Application.initializer({
        name:       "ember-data",
        initialize: setupContainer
      });

      // Deprecated initializers to satisfy old code that depended on them

      Application.initializer({
        name:       "store",
        after:      "ember-data",
        initialize: K
      });

      Application.initializer({
        name:       "activeModelAdapter",
        before:     "store",
        initialize: K
      });

      Application.initializer({
        name:       "transforms",
        before:     "store",
        initialize: K
      });

      Application.initializer({
        name:       "data-adapter",
        before:     "store",
        initialize: K
      });

      Application.initializer({
        name:       "injectStore",
        before:     "store",
        initialize: K
      });
    });
  });
define("ember-data/lib/ext/date", 
  [],
  function() {
    "use strict";
    /**
      @module ember-data
    */

    /**
      Date.parse with progressive enhancement for ISO 8601 <https://github.com/csnover/js-iso8601>

      © 2011 Colin Snover <http://zetafleet.com>

      Released under MIT license.

      @class Date
      @namespace Ember
      @static
    */
    Ember.Date = Ember.Date || {};

    var origParse = Date.parse, numericKeys = [ 1, 4, 5, 6, 7, 10, 11 ];

    /**
      @method parse
      @param date
    */
    Ember.Date.parse = function (date) {
        var timestamp, struct, minutesOffset = 0;

        // ES5 §15.9.4.2 states that the string should attempt to be parsed as a Date Time String Format string
        // before falling back to any implementation-specific date parsing, so that’s what we do, even if native
        // implementations could be faster
        //              1 YYYY                2 MM       3 DD           4 HH    5 mm       6 ss        7 msec        8 Z 9 ±    10 tzHH    11 tzmm
        if ((struct = /^(\d{4}|[+\-]\d{6})(?:-(\d{2})(?:-(\d{2}))?)?(?:T(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{3}))?)?(?:(Z)|([+\-])(\d{2})(?::(\d{2}))?)?)?$/.exec(date))) {
            // avoid NaN timestamps caused by “undefined” values being passed to Date.UTC
            for (var i = 0, k; (k = numericKeys[i]); ++i) {
                struct[k] = +struct[k] || 0;
            }

            // allow undefined days and months
            struct[2] = (+struct[2] || 1) - 1;
            struct[3] = +struct[3] || 1;

            if (struct[8] !== 'Z' && struct[9] !== undefined) {
                minutesOffset = struct[10] * 60 + struct[11];

                if (struct[9] === '+') {
                    minutesOffset = 0 - minutesOffset;
                }
            }

            timestamp = Date.UTC(struct[1], struct[2], struct[3], struct[4], struct[5] + minutesOffset, struct[6], struct[7]);
        }
        else {
            timestamp = origParse ? origParse(date) : NaN;
        }

        return timestamp;
    };

    if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Date) {
      Date.parse = Ember.Date.parse;
    }
  });
define("ember-data/lib/initializers/data_adapter", 
  ["../system/debug/debug_adapter","exports"],
  function(__dependency1__, __exports__) {
    "use strict";
    var DebugAdapter = __dependency1__["default"];

    /**
      Configures a container with injections on Ember applications
      for the Ember-Data store. Accepts an optional namespace argument.

      @method initializeStoreInjections
      @param {Ember.Container} container
    */
    __exports__["default"] = function initializeDebugAdapter(container){
      container.register('data-adapter:main', DebugAdapter);
    };
  });
define("ember-data/lib/initializers/store", 
  ["../serializers","../adapters","../system/container_proxy","../system/store","exports"],
  function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
    "use strict";
    var JSONSerializer = __dependency1__.JSONSerializer;
    var RESTSerializer = __dependency1__.RESTSerializer;
    var RESTAdapter = __dependency2__.RESTAdapter;
    var ContainerProxy = __dependency3__["default"];
    var Store = __dependency4__["default"];

    /**
      Configures a container for use with an Ember-Data
      store. Accepts an optional namespace argument.

      @method initializeStore
      @param {Ember.Container} container
      @param {Object} [application] an application namespace
    */
    __exports__["default"] = function initializeStore(container, application){
      Ember.deprecate('Specifying a custom Store for Ember Data on your global namespace as `App.Store` ' +
                      'has been deprecated. Please use `App.ApplicationStore` instead.', !(application && application.Store));

      container.register('store:main', container.lookupFactory('store:application') || (application && application.Store) || Store);

      // allow older names to be looked up

      var proxy = new ContainerProxy(container);
      proxy.registerDeprecations([
        {deprecated: 'serializer:_default',  valid: 'serializer:-default'},
        {deprecated: 'serializer:_rest',     valid: 'serializer:-rest'},
        {deprecated: 'adapter:_rest',        valid: 'adapter:-rest'}
      ]);

      // new go forward paths
      container.register('serializer:-default', JSONSerializer);
      container.register('serializer:-rest', RESTSerializer);
      container.register('adapter:-rest', RESTAdapter);

      // Eagerly generate the store so defaultStore is populated.
      // TODO: Do this in a finisher hook
      container.lookup('store:main');
    };
  });
define("ember-data/lib/initializers/store_injections", 
  ["exports"],
  function(__exports__) {
    "use strict";
    /**
      Configures a container with injections on Ember applications
      for the Ember-Data store. Accepts an optional namespace argument.

      @method initializeStoreInjections
      @param {Ember.Container} container
    */
    __exports__["default"] = function initializeStoreInjections(container){
      container.injection('controller',   'store', 'store:main');
      container.injection('route',        'store', 'store:main');
      container.injection('serializer',   'store', 'store:main');
      container.injection('data-adapter', 'store', 'store:main');
    };
  });
define("ember-data/lib/initializers/transforms", 
  ["../transforms","exports"],
  function(__dependency1__, __exports__) {
    "use strict";
    var BooleanTransform = __dependency1__.BooleanTransform;
    var DateTransform = __dependency1__.DateTransform;
    var StringTransform = __dependency1__.StringTransform;
    var NumberTransform = __dependency1__.NumberTransform;

    /**
      Configures a container for use with Ember-Data
      transforms.

      @method initializeTransforms
      @param {Ember.Container} container
    */
    __exports__["default"] = function initializeTransforms(container){
      container.register('transform:boolean', BooleanTransform);
      container.register('transform:date',    DateTransform);
      container.register('transform:number',  NumberTransform);
      container.register('transform:string',  StringTransform);
    };
  });
define("ember-data/lib/main", 
  ["./core","./ext/date","./system/store","./system/model","./system/changes","./system/adapter","./system/debug","./system/record_arrays","./system/record_array_manager","./adapters","./serializers/json_serializer","./serializers/rest_serializer","../../ember-inflector/lib/main","../../activemodel-adapter/lib/main","./transforms","./system/relationships","./ember-initializer","./setup-container","./system/container_proxy","exports"],
  function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __dependency18__, __dependency19__, __exports__) {
    "use strict";
    /**
      Ember Data

      @module ember-data
      @main ember-data
    */

    // support RSVP 2.x via resolve,  but prefer RSVP 3.x's Promise.cast
    Ember.RSVP.Promise.cast = Ember.RSVP.Promise.cast || Ember.RSVP.resolve;

    var DS = __dependency1__["default"];

    var Store = __dependency3__.Store;
    var PromiseArray = __dependency3__.PromiseArray;
    var PromiseObject = __dependency3__.PromiseObject;
    var Model = __dependency4__.Model;
    var Errors = __dependency4__.Errors;
    var RootState = __dependency4__.RootState;
    var attr = __dependency4__.attr;
    var AttributeChange = __dependency5__.AttributeChange;
    var RelationshipChange = __dependency5__.RelationshipChange;
    var RelationshipChangeAdd = __dependency5__.RelationshipChangeAdd;
    var RelationshipChangeRemove = __dependency5__.RelationshipChangeRemove;
    var OneToManyChange = __dependency5__.OneToManyChange;
    var ManyToNoneChange = __dependency5__.ManyToNoneChange;
    var OneToOneChange = __dependency5__.OneToOneChange;
    var ManyToManyChange = __dependency5__.ManyToManyChange;
    var InvalidError = __dependency6__.InvalidError;
    var Adapter = __dependency6__.Adapter;
    var DebugAdapter = __dependency7__["default"];
    var RecordArray = __dependency8__.RecordArray;
    var FilteredRecordArray = __dependency8__.FilteredRecordArray;
    var AdapterPopulatedRecordArray = __dependency8__.AdapterPopulatedRecordArray;
    var ManyArray = __dependency8__.ManyArray;
    var RecordArrayManager = __dependency9__["default"];
    var RESTAdapter = __dependency10__.RESTAdapter;
    var FixtureAdapter = __dependency10__.FixtureAdapter;
    var JSONSerializer = __dependency11__["default"];
    var RESTSerializer = __dependency12__["default"];
    var ActiveModelAdapter = __dependency14__.ActiveModelAdapter;
    var ActiveModelSerializer = __dependency14__.ActiveModelSerializer;
    var EmbeddedRecordsMixin = __dependency14__.EmbeddedRecordsMixin;

    var Transform = __dependency15__.Transform;
    var DateTransform = __dependency15__.DateTransform;
    var NumberTransform = __dependency15__.NumberTransform;
    var StringTransform = __dependency15__.StringTransform;
    var BooleanTransform = __dependency15__.BooleanTransform;

    var hasMany = __dependency16__.hasMany;
    var belongsTo = __dependency16__.belongsTo;
    var setupContainer = __dependency18__["default"];

    var ContainerProxy = __dependency19__["default"];

    DS.Store         = Store;
    DS.PromiseArray  = PromiseArray;
    DS.PromiseObject = PromiseObject;

    DS.Model     = Model;
    DS.RootState = RootState;
    DS.attr      = attr;
    DS.Errors    = Errors;

    DS.AttributeChange       = AttributeChange;
    DS.RelationshipChange    = RelationshipChange;
    DS.RelationshipChangeAdd = RelationshipChangeAdd;
    DS.OneToManyChange       = OneToManyChange;
    DS.ManyToNoneChange      = OneToManyChange;
    DS.OneToOneChange        = OneToOneChange;
    DS.ManyToManyChange      = ManyToManyChange;

    DS.Adapter      = Adapter;
    DS.InvalidError = InvalidError;

    DS.DebugAdapter = DebugAdapter;

    DS.RecordArray                 = RecordArray;
    DS.FilteredRecordArray         = FilteredRecordArray;
    DS.AdapterPopulatedRecordArray = AdapterPopulatedRecordArray;
    DS.ManyArray                   = ManyArray;

    DS.RecordArrayManager = RecordArrayManager;

    DS.RESTAdapter    = RESTAdapter;
    DS.FixtureAdapter = FixtureAdapter;

    DS.RESTSerializer = RESTSerializer;
    DS.JSONSerializer = JSONSerializer;

    DS.Transform       = Transform;
    DS.DateTransform   = DateTransform;
    DS.StringTransform = StringTransform;
    DS.NumberTransform = NumberTransform;
    DS.BooleanTransform = BooleanTransform;

    DS.ActiveModelAdapter    = ActiveModelAdapter;
    DS.ActiveModelSerializer = ActiveModelSerializer;
    DS.EmbeddedRecordsMixin  = EmbeddedRecordsMixin;

    DS.belongsTo = belongsTo;
    DS.hasMany   = hasMany;

    DS.ContainerProxy = ContainerProxy;

    DS._setupContainer = setupContainer;

    Ember.lookup.DS = DS;

    __exports__["default"] = DS;
  });
define("ember-data/lib/serializers", 
  ["./serializers/json_serializer","./serializers/rest_serializer","exports"],
  function(__dependency1__, __dependency2__, __exports__) {
    "use strict";
    var JSONSerializer = __dependency1__["default"];
    var RESTSerializer = __dependency2__["default"];

    __exports__.JSONSerializer = JSONSerializer;
    __exports__.RESTSerializer = RESTSerializer;
  });
define("ember-data/lib/serializers/json_serializer", 
  ["../system/changes","exports"],
  function(__dependency1__, __exports__) {
    "use strict";
    var RelationshipChange = __dependency1__.RelationshipChange;
    var get = Ember.get, set = Ember.set, isNone = Ember.isNone,
        map = Ember.ArrayPolyfills.map;

    /**
      In Ember Data a Serializer is used to serialize and deserialize
      records when they are transferred in and out of an external source.
      This process involves normalizing property names, transforming
      attribute values and serializing relationships.

      For maximum performance Ember Data recommends you use the
      [RESTSerializer](DS.RESTSerializer.html) or one of its subclasses.

      `JSONSerializer` is useful for simpler or legacy backends that may
      not support the http://jsonapi.org/ spec.

      @class JSONSerializer
      @namespace DS
    */
    var JSONSerializer = Ember.Object.extend({
      /**
        The primaryKey is used when serializing and deserializing
        data. Ember Data always uses the `id` property to store the id of
        the record. The external source may not always follow this
        convention. In these cases it is useful to override the
        primaryKey property to match the primaryKey of your external
        store.

        Example

        ```javascript
        App.ApplicationSerializer = DS.JSONSerializer.extend({
          primaryKey: '_id'
        });
        ```

        @property primaryKey
        @type {String}
        @default 'id'
      */
      primaryKey: 'id',

      /**
        The `attrs` object can be used to declare a simple mapping between
        property names on `DS.Model` records and payload keys in the
        serialized JSON object representing the record. An object with the
        propery `key` can also be used to designate the attribute's key on
        the response payload.

        Example

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

        App.PersonSerializer = DS.JSONSerializer.extend({
          attrs: {
            admin: 'is_admin',
            occupation: {key: 'career'}
          }
        });
        ```

        @property attrs
        @type {Object}
      */

      /**
       Given a subclass of `DS.Model` and a JSON object this method will
       iterate through each attribute of the `DS.Model` and invoke the
       `DS.Transform#deserialize` method on the matching property of the
       JSON object.  This method is typically called after the
       serializer's `normalize` method.

       @method applyTransforms
       @private
       @param {subclass of DS.Model} type
       @param {Object} data The data to transform
       @return {Object} data The transformed data object
      */
      applyTransforms: function(type, data) {
        type.eachTransformedAttribute(function(key, type) {
          var transform = this.transformFor(type);
          data[key] = transform.deserialize(data[key]);
        }, this);

        return data;
      },

      /**
        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.

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

        Example

        ```javascript
        App.ApplicationSerializer = DS.JSONSerializer.extend({
          normalize: function(type, hash) {
            var fields = Ember.get(type, 'fields');
            fields.forEach(function(field) {
              var payloadField = Ember.String.underscore(field);
              if (field === payloadField) { return; }

              hash[field] = hash[payloadField];
              delete hash[payloadField];
            });
            return this._super.apply(this, arguments);
          }
        });
        ```

        @method normalize
        @param {subclass of DS.Model} type
        @param {Object} hash
        @return {Object}
      */
      normalize: function(type, hash) {
        if (!hash) { return hash; }

        this.normalizeId(hash);
        this.normalizeUsingDeclaredMapping(type, hash);
        this.applyTransforms(type, hash);
        return hash;
      },

      /**
        @method normalizeUsingDeclaredMapping
        @private
      */
      normalizeUsingDeclaredMapping: function(type, hash) {
        var attrs = get(this, 'attrs'), payloadKey, key;

        if (attrs) {
          for (key in attrs) {
            payloadKey = attrs[key];
            if (payloadKey && payloadKey.key) {
              payloadKey = payloadKey.key;
            }
            if (typeof payloadKey === 'string') {
              hash[key] = hash[payloadKey];
              delete hash[payloadKey];
            }
          }
        }
      },
      /**
        @method normalizeId
        @private
      */
      normalizeId: function(hash) {
        var primaryKey = get(this, 'primaryKey');

        if (primaryKey === 'id') { return; }

        hash.id = hash[primaryKey];
        delete hash[primaryKey];
      },

      // SERIALIZE
      /**
        Called when a record is saved in order to convert the
        record into JSON.

        By default, it creates a JSON object with a key for
        each attribute and belongsTo relationship.

        For example, consider this model:

        ```javascript
        App.Comment = DS.Model.extend({
          title: DS.attr(),
          body: DS.attr(),

          author: DS.belongsTo('user')
        });
        ```

        The default serialization would create a JSON object like:

        ```javascript
        {
          "title": "Rails is unagi",
          "body": "Rails? Omakase? O_O",
          "author": 12
        }
        ```

        By default, attributes are passed through as-is, unless
        you specified an attribute type (`DS.attr('date')`). If
        you specify a transform, the JavaScript value will be
        serialized when inserted into the JSON hash.

        By default, belongs-to relationships are converted into
        IDs when inserted into the JSON hash.

        ## IDs

        `serialize` takes an options hash with a single option:
        `includeId`. If this option is `true`, `serialize` will,
        by default include the ID in the JSON object it builds.

        The adapter passes in `includeId: true` when serializing
        a record for `createRecord`, but not for `updateRecord`.

        ## Customization

        Your server may expect a different JSON format than the
        built-in serialization format.

        In that case, you can implement `serialize` yourself and
        return a JSON hash of your choosing.

        ```javascript
        App.PostSerializer = DS.JSONSerializer.extend({
          serialize: function(post, options) {
            var json = {
              POST_TTL: post.get('title'),
              POST_BDY: post.get('body'),
              POST_CMS: post.get('comments').mapProperty('id')
            }

            if (options.includeId) {
              json.POST_ID_ = post.get('id');
            }

            return json;
          }
        });
        ```

        ## Customizing an App-Wide Serializer

        If you want to define a serializer for your entire
        application, you'll probably want to use `eachAttribute`
        and `eachRelationship` on the record.

        ```javascript
        App.ApplicationSerializer = DS.JSONSerializer.extend({
          serialize: function(record, options) {
            var json = {};

            record.eachAttribute(function(name) {
              json[serverAttributeName(name)] = record.get(name);
            })

            record.eachRelationship(function(name, relationship) {
              if (relationship.kind === 'hasMany') {
                json[serverHasManyName(name)] = record.get(name).mapBy('id');
              }
            });

            if (options.includeId) {
              json.ID_ = record.get('id');
            }

            return json;
          }
        });

        function serverAttributeName(attribute) {
          return attribute.underscore().toUpperCase();
        }

        function serverHasManyName(name) {
          return serverAttributeName(name.singularize()) + "_IDS";
        }
        ```

        This serializer will generate JSON that looks like this:

        ```javascript
        {
          "TITLE": "Rails is omakase",
          "BODY": "Yep. Omakase.",
          "COMMENT_IDS": [ 1, 2, 3 ]
        }
        ```

        ## Tweaking the Default JSON

        If you just want to do some small tweaks on the default JSON,
        you can call super first and make the tweaks on the returned
        JSON.

        ```javascript
        App.PostSerializer = DS.JSONSerializer.extend({
          serialize: function(record, options) {
            var json = this._super.apply(this, arguments);

            json.subject = json.title;
            delete json.title;

            return json;
          }
        });
        ```

        @method serialize
        @param {subclass of DS.Model} record
        @param {Object} options
        @return {Object} json
      */
      serialize: function(record, options) {
        var json = {};

        if (options && options.includeId) {
          var id = get(record, 'id');

          if (id) {
            json[get(this, 'primaryKey')] = id;
          }
        }

        record.eachAttribute(function(key, attribute) {
          this.serializeAttribute(record, json, key, attribute);
        }, this);

        record.eachRelationship(function(key, relationship) {
          if (relationship.kind === 'belongsTo') {
            this.serializeBelongsTo(record, json, relationship);
          } else if (relationship.kind === 'hasMany') {
            this.serializeHasMany(record, json, relationship);
          }
        }, this);

        return json;
      },

      /**
       `serializeAttribute` can be used to customize how `DS.attr`
       properties are serialized

       For example if you wanted to ensure all your attributes were always
       serialized as properties on an `attributes` object you could
       write:

       ```javascript
       App.ApplicationSerializer = DS.JSONSerializer.extend({
         serializeAttribute: function(record, json, key, attributes) {
           json.attributes = json.attributes || {};
           this._super(record, json.attributes, key, attributes);
         }
       });
       ```

       @method serializeAttribute
       @param {DS.Model} record
       @param {Object} json
       @param {String} key
       @param {Object} attribute
      */
      serializeAttribute: function(record, json, key, attribute) {
        var attrs = get(this, 'attrs');
        var value = get(record, key), type = attribute.type;

        if (type) {
          var transform = this.transformFor(type);
          value = transform.serialize(value);
        }

        // if provided, use the mapping provided by `attrs` in
        // the serializer
        key = attrs && attrs[key] || (this.keyForAttribute ? this.keyForAttribute(key) : key);

        json[key] = value;
      },

      /**
       `serializeBelongsTo` can be used to customize how `DS.belongsTo`
       properties are serialized.

       Example

       ```javascript
       App.PostSerializer = DS.JSONSerializer.extend({
         serializeBelongsTo: function(record, json, relationship) {
           var key = relationship.key;

           var belongsTo = get(record, key);

           key = this.keyForRelationship ? this.keyForRelationship(key, "belongsTo") : key;

           json[key] = Ember.isNone(belongsTo) ? belongsTo : belongsTo.toJSON();
         }
       });
       ```

       @method serializeBelongsTo
       @param {DS.Model} record
       @param {Object} json
       @param {Object} relationship
      */
      serializeBelongsTo: function(record, json, relationship) {
        var key = relationship.key;

        var belongsTo = get(record, key);

        key = this.keyForRelationship ? this.keyForRelationship(key, "belongsTo") : key;

        if (isNone(belongsTo)) {
          json[key] = belongsTo;
        } else {
          json[key] = get(belongsTo, 'id');
        }

        if (relationship.options.polymorphic) {
          this.serializePolymorphicType(record, json, relationship);
        }
      },

      /**
       `serializeHasMany` can be used to customize how `DS.hasMany`
       properties are serialized.

       Example

       ```javascript
       App.PostSerializer = DS.JSONSerializer.extend({
         serializeHasMany: function(record, json, relationship) {
           var key = relationship.key;
           if (key === 'comments') {
             return;
           } else {
             this._super.apply(this, arguments);
           }
         }
       });
       ```

       @method serializeHasMany
       @param {DS.Model} record
       @param {Object} json
       @param {Object} relationship
      */
      serializeHasMany: function(record, json, relationship) {
        var key = relationship.key;
        var payloadKey = this.keyForRelationship ? this.keyForRelationship(key, "hasMany") : key;
        var relationshipType = RelationshipChange.determineRelationshipType(record.constructor, relationship);

        if (relationshipType === 'manyToNone' || relationshipType === 'manyToMany') {
          json[payloadKey] = get(record, key).mapBy('id');
          // TODO support for polymorphic manyToNone and manyToMany relationships
        }
      },

      /**
        You can use this method to customize how polymorphic objects are
        serialized. Objects are considered to be polymorphic if
        `{polymorphic: true}` is pass as the second argument to the
        `DS.belongsTo` function.

        Example

        ```javascript
        App.CommentSerializer = DS.JSONSerializer.extend({
          serializePolymorphicType: 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;
          }
        });
       ```

        @method serializePolymorphicType
        @param {DS.Model} record
        @param {Object} json
        @param {Object} relationship
      */
      serializePolymorphicType: Ember.K,

      // EXTRACT

      /**
        The `extract` method is used to deserialize payload data from the
        server. By default the `JSONSerializer` does not push the records
        into the store. However records that subclass `JSONSerializer`
        such as the `RESTSerializer` may push records into the store as
        part of the extract call.

        This method delegates to a more specific extract method based on
        the `requestType`.

        Example

        ```javascript
        var get = Ember.get;
        socket.on('message', function(message) {
          var modelName = message.model;
          var data = message.data;
          var type = store.modelFor(modelName);
          var serializer = store.serializerFor(type.typeKey);
          var record = serializer.extract(store, type, data, get(data, 'id'), 'single');
          store.push(modelName, record);
        });
        ```

        @method extract
        @param {DS.Store} store
        @param {subclass of DS.Model} type
        @param {Object} payload
        @param {String or Number} id
        @param {String} requestType
        @return {Object} json The deserialized payload
      */
      extract: function(store, type, payload, id, requestType) {
        this.extractMeta(store, type, payload);

        var specificExtract = "extract" + requestType.charAt(0).toUpperCase() + requestType.substr(1);
        return this[specificExtract](store, type, payload, id, requestType);
      },

      /**
        `extractFindAll` is a hook into the extract method used when a
        call is made to `DS.Store#findAll`. By default this method is an
        alias for [extractArray](#method_extractArray).

        @method extractFindAll
        @param {DS.Store} store
        @param {subclass of DS.Model} type
        @param {Object} payload
        @return {Array} array An array of deserialized objects
      */
      extractFindAll: function(store, type, payload){
        return this.extractArray(store, type, payload);
      },
      /**
        `extractFindQuery` is a hook into the extract method used when a
        call is made to `DS.Store#findQuery`. By default this method is an
        alias for [extractArray](#method_extractArray).

        @method extractFindQuery
        @param {DS.Store} store
        @param {subclass of DS.Model} type
        @param {Object} payload
        @return {Array} array An array of deserialized objects
      */
      extractFindQuery: function(store, type, payload){
        return this.extractArray(store, type, payload);
      },
      /**
        `extractFindMany` is a hook into the extract method used when a
        call is made to `DS.Store#findMany`. By default this method is
        alias for [extractArray](#method_extractArray).

        @method extractFindMany
        @param {DS.Store} store
        @param {subclass of DS.Model} type
        @param {Object} payload
        @return {Array} array An array of deserialized objects
      */
      extractFindMany: function(store, type, payload){
        return this.extractArray(store, type, payload);
      },
      /**
        `extractFindHasMany` is a hook into the extract method used when a
        call is made to `DS.Store#findHasMany`. By default this method is
        alias for [extractArray](#method_extractArray).

        @method extractFindHasMany
        @param {DS.Store} store
        @param {subclass of DS.Model} type
        @param {Object} payload
        @return {Array} array An array of deserialized objects
      */
      extractFindHasMany: function(store, type, payload){
        return this.extractArray(store, type, payload);
      },

      /**
        `extractCreateRecord` is a hook into the extract method used when a
        call is made to `DS.Store#createRecord`. By default this method is
        alias for [extractSave](#method_extractSave).

        @method extractCreateRecord
        @param {DS.Store} store
        @param {subclass of DS.Model} type
        @param {Object} payload
        @return {Object} json The deserialized payload
      */
      extractCreateRecord: function(store, type, payload) {
        return this.extractSave(store, type, payload);
      },
      /**
        `extractUpdateRecord` is a hook into the extract method used when
        a call is made to `DS.Store#update`. By default this method is alias
        for [extractSave](#method_extractSave).

        @method extractUpdateRecord
        @param {DS.Store} store
        @param {subclass of DS.Model} type
        @param {Object} payload
        @return {Object} json The deserialized payload
      */
      extractUpdateRecord: function(store, type, payload) {
        return this.extractSave(store, type, payload);
      },
      /**
        `extractDeleteRecord` is a hook into the extract method used when
        a call is made to `DS.Store#deleteRecord`. By default this method is
        alias for [extractSave](#method_extractSave).

        @method extractDeleteRecord
        @param {DS.Store} store
        @param {subclass of DS.Model} type
        @param {Object} payload
        @return {Object} json The deserialized payload
      */
      extractDeleteRecord: function(store, type, payload) {
        return this.extractSave(store, type, payload);
      },

      /**
        `extractFind` is a hook into the extract method used when
        a call is made to `DS.Store#find`. By default this method is
        alias for [extractSingle](#method_extractSingle).

        @method extractFind
        @param {DS.Store} store
        @param {subclass of DS.Model} type
        @param {Object} payload
        @return {Object} json The deserialized payload
      */
      extractFind: function(store, type, payload) {
        return this.extractSingle(store, type, payload);
      },
      /**
        `extractFindBelongsTo` is a hook into the extract method used when
        a call is made to `DS.Store#findBelongsTo`. By default this method is
        alias for [extractSingle](#method_extractSingle).

        @method extractFindBelongsTo
        @param {DS.Store} store
        @param {subclass of DS.Model} type
        @param {Object} payload
        @return {Object} json The deserialized payload
      */
      extractFindBelongsTo: function(store, type, payload) {
        return this.extractSingle(store, type, payload);
      },
      /**
        `extractSave` is a hook into the extract method used when a call
        is made to `DS.Model#save`. By default this method is alias
        for [extractSingle](#method_extractSingle).

        @method extractSave
        @param {DS.Store} store
        @param {subclass of DS.Model} type
        @param {Object} payload
        @return {Object} json The deserialized payload
      */
      extractSave: function(store, type, payload) {
        return this.extractSingle(store, type, payload);
      },

      /**
        `extractSingle` is used to deserialize a single record returned
        from the adapter.

        Example

        ```javascript
        App.PostSerializer = DS.JSONSerializer.extend({
          extractSingle: function(store, type, payload) {
            payload.comments = payload._embedded.comment;
            delete payload._embedded;

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

        @method extractSingle
        @param {DS.Store} store
        @param {subclass of DS.Model} type
        @param {Object} payload
        @return {Object} json The deserialized payload
      */
      extractSingle: function(store, type, payload) {
        return this.normalize(type, payload);
      },

      /**
        `extractArray` is used to deserialize an array of records
        returned from the adapter.

        Example

        ```javascript
        App.PostSerializer = DS.JSONSerializer.extend({
          extractArray: function(store, type, payload) {
            return payload.map(function(json) {
              return this.extractSingle(store, type, json);
            }, this);
          }
        });
        ```

        @method extractArray
        @param {DS.Store} store
        @param {subclass of DS.Model} type
        @param {Object} payload
        @return {Array} array An array of deserialized objects
      */
      extractArray: function(store, type, arrayPayload) {
        var serializer = this;
        return map.call(arrayPayload, function(singlePayload) {
          return serializer.normalize(type, singlePayload);
        });
      },

      /**
        `extractMeta` is used to deserialize any meta information in the
        adapter payload. By default Ember Data expects meta information to
        be located on the `meta` property of the payload object.

        Example

        ```javascript
        App.PostSerializer = DS.JSONSerializer.extend({
          extractMeta: function(store, type, payload) {
            if (payload && payload._pagination) {
              store.metaForType(type, payload._pagination);
              delete payload._pagination;
            }
          }
        });
        ```

        @method extractMeta
        @param {DS.Store} store
        @param {subclass of DS.Model} type
        @param {Object} payload
      */
      extractMeta: function(store, type, payload) {
        if (payload && payload.meta) {
          store.metaForType(type, payload.meta);
          delete payload.meta;
        }
      },

      /**
       `keyForAttribute` can be used to define rules for how to convert an
       attribute name in your model to a key in your JSON.

       Example

       ```javascript
       App.ApplicationSerializer = DS.RESTSerializer.extend({
         keyForAttribute: function(attr) {
           return Ember.String.underscore(attr).toUpperCase();
         }
       });
       ```

       @method keyForAttribute
       @param {String} key
       @return {String} normalized key
      */


      /**
       `keyForRelationship` can be used to define a custom key when
       serializing relationship properties. By default `JSONSerializer`
       does not provide an implementation of this method.

       Example

        ```javascript
        App.PostSerializer = DS.JSONSerializer.extend({
          keyForRelationship: function(key, relationship) {
             return 'rel_' + Ember.String.underscore(key);
          }
        });
        ```

       @method keyForRelationship
       @param {String} key
       @param {String} relationship type
       @return {String} normalized key
      */

      // HELPERS

      /**
       @method transformFor
       @private
       @param {String} attributeType
       @param {Boolean} skipAssertion
       @return {DS.Transform} transform
      */
      transformFor: function(attributeType, skipAssertion) {
        var transform = this.container.lookup('transform:' + attributeType);
        Ember.assert("Unable to find transform for '" + attributeType + "'", skipAssertion || !!transform);
        return transform;
      }
    });

    __exports__["default"] = JSONSerializer;
  });
define("ember-data/lib/serializers/rest_serializer", 
  ["./json_serializer","ember-inflector/lib/system/string","exports"],
  function(__dependency1__, __dependency2__, __exports__) {
    "use strict";
    /**
      @module ember-data
    */

    var JSONSerializer = __dependency1__["default"];
    var get = Ember.get, set = Ember.set;
    var forEach = Ember.ArrayPolyfills.forEach;
    var map = Ember.ArrayPolyfills.map;

    var singularize = __dependency2__.singularize;
    var camelize = Ember.String.camelize;

    function coerceId(id) {
      return id == null ? null : id+'';
    }

    /**
      Normally, applications will use the `RESTSerializer` by implementing
      the `normalize` method and individual normalizations under
      `normalizeHash`.

      This allows you to do whatever kind of munging you need, and is
      especially useful if your server is inconsistent and you need to
      do munging differently for many different kinds of responses.

      See the `normalize` documentation for more information.

      ## Across the Board Normalization

      There are also a number of hooks that you might find useful to defined
      across-the-board rules for your payload. These rules will be useful
      if your server is consistent, or if you're building an adapter for
      an infrastructure service, like Parse, and want to encode service
      conventions.

      For example, if all of your keys are underscored and all-caps, but
      otherwise consistent with the names you use in your models, you
      can implement across-the-board rules for how to convert an attribute
      name in your model to a key in your JSON.

      ```js
      App.ApplicationSerializer = DS.RESTSerializer.extend({
        keyForAttribute: function(attr) {
          return Ember.String.underscore(attr).toUpperCase();
        }
      });
      ```

      You can also implement `keyForRelationship`, which takes the name
      of the relationship as the first parameter, and the kind of
      relationship (`hasMany` or `belongsTo`) as the second parameter.

      @class RESTSerializer
      @namespace DS
      @extends DS.JSONSerializer
    */
    var RESTSerializer = JSONSerializer.extend({
      /**
        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 implementation 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
        @return {Object}
      */
      normalize: 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);
        }

        this.applyTransforms(type, hash);
        return hash;
      },

      /**
        You can use this method to normalize all payloads, regardless of whether they
        represent single records or an array.

        For example, you might want to remove some extraneous data from the payload:

        ```js
        App.ApplicationSerializer = DS.RESTSerializer.extend({
          normalizePayload: function(payload) {
            delete payload.version;
            delete payload.status;
            return payload;
          }
        });
        ```

        @method normalizePayload
        @param {Object} payload
        @return {Object} the normalized payload
      */
      normalizePayload: function(payload) {
        return payload;
      },

      /**
        @method normalizeAttributes
        @private
      */
      normalizeAttributes: function(type, hash) {
        var payloadKey, key;

        if (this.keyForAttribute) {
          type.eachAttribute(function(key) {
            payloadKey = this.keyForAttribute(key);
            if (key === payloadKey) { return; }

            hash[key] = hash[payloadKey];
            delete hash[payloadKey];
          }, this);
        }
      },

      /**
        @method normalizeRelationships
        @private
      */
      normalizeRelationships: function(type, hash) {
        var payloadKey, key;

        if (this.keyForRelationship) {
          type.eachRelationship(function(key, relationship) {
            payloadKey = this.keyForRelationship(key, relationship.kind);
            if (key === payloadKey) { return; }

            hash[key] = hash[payloadKey];
            delete hash[payloadKey];
          }, this);
        }
      },

      /**
        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) {
            var comments = payload._embedded.comment;
            delete payload._embedded;

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

          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} primaryType
        @param {Object} payload
        @param {String} recordId
        @return {Object} the primary response to the original request
      */
      extractSingle: function(store, primaryType, payload, recordId) {
        payload = this.normalizePayload(payload);
        var primaryTypeName = primaryType.typeKey,
            primaryRecord;

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

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

          /*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;
      },

      /**
        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) {
            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);
          },

          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} primaryType
        @param {Object} payload
        @return {Array} The primary array that was returned in response
          to the original query.
      */
      extractArray: function(store, primaryType, payload) {
        payload = this.normalizePayload(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 && (type.typeKey === 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;
      },

      /**
        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
      */
      pushPayload: function(store, payload) {
        payload = this.normalizePayload(payload);

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

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

          store.pushMany(typeName, normalizedArray);
        }
      },

      /**
        This method is used to convert each JSON root key in the payload
        into a typeKey that it can use to look up the appropriate model for
        that part of the payload. By default the typeKey for a model is its
        name in camelCase, so if your JSON root key is 'fast-car' you would
        use typeForRoot to convert it to 'fastCar' so that Ember Data finds
        the `FastCar` model.

        If you diverge from this norm you should also consider changes to
        store._normalizeTypeKey as well.

        For example, your server may return prefixed root keys like so:

        ```js
        {
          "response-fast-car": {
            "id": "1",
            "name": "corvette"
          }
        }
        ```

        In order for Ember Data to know that the model corresponding to
        the 'response-fast-car' hash is `FastCar` (typeKey: 'fastCar'),
        you can override typeForRoot to convert 'response-fast-car' to
        'fastCar' like so:

        ```js
        App.ApplicationSerializer = DS.RESTSerializer.extend({
          typeForRoot: function(root) {
            // 'response-fast-car' should become 'fast-car'
            var subRoot = root.substring(9);

            // _super normalizes 'fast-car' to 'fastCar'
            return this._super(subRoot);
          }
        });
        ```

        @method typeForRoot
        @param {String} key
        @return {String} the model's typeKey
      */
      typeForRoot: function(key) {
        return camelize(singularize(key));
      },

      // SERIALIZE

      /**
        Called when a record is saved in order to convert the
        record into JSON.

        By default, it creates a JSON object with a key for
        each attribute and belongsTo relationship.

        For example, consider this model:

        ```js
        App.Comment = DS.Model.extend({
          title: DS.attr(),
          body: DS.attr(),

          author: DS.belongsTo('user')
        });
        ```

        The default serialization would create a JSON object like:

        ```js
        {
          "title": "Rails is unagi",
          "body": "Rails? Omakase? O_O",
          "author": 12
        }
        ```

        By default, attributes are passed through as-is, unless
        you specified an attribute type (`DS.attr('date')`). If
        you specify a transform, the JavaScript value will be
        serialized when inserted into the JSON hash.

        By default, belongs-to relationships are converted into
        IDs when inserted into the JSON hash.

        ## IDs

        `serialize` takes an options hash with a single option:
        `includeId`. If this option is `true`, `serialize` will,
        by default include the ID in the JSON object it builds.

        The adapter passes in `includeId: true` when serializing
        a record for `createRecord`, but not for `updateRecord`.

        ## Customization

        Your server may expect a different JSON format than the
        built-in serialization format.

        In that case, you can implement `serialize` yourself and
        return a JSON hash of your choosing.

        ```js
        App.PostSerializer = DS.RESTSerializer.extend({
          serialize: function(post, options) {
            var json = {
              POST_TTL: post.get('title'),
              POST_BDY: post.get('body'),
              POST_CMS: post.get('comments').mapProperty('id')
            }

            if (options.includeId) {
              json.POST_ID_ = post.get('id');
            }

            return json;
          }
        });
        ```

        ## Customizing an App-Wide Serializer

        If you want to define a serializer for your entire
        application, you'll probably want to use `eachAttribute`
        and `eachRelationship` on the record.

        ```js
        App.ApplicationSerializer = DS.RESTSerializer.extend({
          serialize: function(record, options) {
            var json = {};

            record.eachAttribute(function(name) {
              json[serverAttributeName(name)] = record.get(name);
            })

            record.eachRelationship(function(name, relationship) {
              if (relationship.kind === 'hasMany') {
                json[serverHasManyName(name)] = record.get(name).mapBy('id');
              }
            });

            if (options.includeId) {
              json.ID_ = record.get('id');
            }

            return json;
          }
        });

        function serverAttributeName(attribute) {
          return attribute.underscore().toUpperCase();
        }

        function serverHasManyName(name) {
          return serverAttributeName(name.singularize()) + "_IDS";
        }
        ```

        This serializer will generate JSON that looks like this:

        ```js
        {
          "TITLE": "Rails is omakase",
          "BODY": "Yep. Omakase.",
          "COMMENT_IDS": [ 1, 2, 3 ]
        }
        ```

        ## Tweaking the Default JSON

        If you just want to do some small tweaks on the default JSON,
        you can call super first and make the tweaks on the returned
        JSON.

        ```js
        App.PostSerializer = DS.RESTSerializer.extend({
          serialize: function(record, options) {
            var json = this._super(record, options);

            json.subject = json.title;
            delete json.title;

            return json;
          }
        });
        ```

        @method serialize
        @param record
        @param options
      */
      serialize: function(record, options) {
        return this._super.apply(this, arguments);
      },

      /**
        You can use this method to customize the root keys serialized into the JSON.
        By default the REST Serializer sends the typeKey of a model, whih is a camelized
        version of the name.

        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
      */
      serializeIntoHash: function(hash, type, record, options) {
        hash[type.typeKey] = this.serialize(record, options);
      },

      /**
        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
      */
      serializePolymorphicType: 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;
      }
    });

    __exports__["default"] = RESTSerializer;
  });
define("ember-data/lib/setup-container", 
  ["./initializers/store","./initializers/transforms","./initializers/store_injections","./initializers/data_adapter","../../../activemodel-adapter/lib/setup-container","exports"],
  function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
    "use strict";
    var initializeStore = __dependency1__["default"];
    var initializeTransforms = __dependency2__["default"];
    var initializeStoreInjections = __dependency3__["default"];
    var initializeDataAdapter = __dependency4__["default"];
    var setupActiveModelContainer = __dependency5__["default"];

    __exports__["default"] = function setupContainer(container, application){
      // application is not a required argument. This ensures
      // testing setups can setup a container without booting an
      // entire ember application.

      initializeDataAdapter(container, application);
      initializeTransforms(container, application);
      initializeStoreInjections(container, application);
      initializeStore(container, application);
      setupActiveModelContainer(container, application);
    };
  });
define("ember-data/lib/system/adapter", 
  ["exports"],
  function(__exports__) {
    "use strict";
    /**
      @module ember-data
    */

    var get = Ember.get, set = Ember.set;
    var map = Ember.ArrayPolyfills.map;

    var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack'];

    /**
      A `DS.InvalidError` is used by an adapter to signal the external API
      was unable to process a request because the content was not
      semantically correct or meaningful per the API. Usually this means a
      record failed some form of server side validation. When a promise
      from an adapter is rejected with a `DS.InvalidError` the record will
      transition to the `invalid` state and the errors will be set to the
      `errors` property on the record.

      Example

      ```javascript
      App.ApplicationAdapter = DS.RESTAdapter.extend({
        ajaxError: function(jqXHR) {
          var error = this._super(jqXHR);

          if (jqXHR && jqXHR.status === 422) {
            var jsonErrors = Ember.$.parseJSON(jqXHR.responseText)["errors"];
            return new DS.InvalidError(jsonErrors);
          } else {
            return error;
          }
        }
      });
      ```

      The `DS.InvalidError` must be constructed with a single object whose
      keys are the invalid model properties, and whose values are the
      corresponding error messages. For example:

      ```javascript
      return new DS.InvalidError({
        length: 'Must be less than 15',
        name: 'Must not be blank
      });
      ```

      @class InvalidError
      @namespace DS
    */
    var InvalidError = function(errors) {
      var tmp = Error.prototype.constructor.call(this, "The backend rejected the commit because it was invalid: " + Ember.inspect(errors));
      this.errors = errors;

      for (var i=0, l=errorProps.length; i<l; i++) {
        this[errorProps[i]] = tmp[errorProps[i]];
      }
    };
    InvalidError.prototype = Ember.create(Error.prototype);

    /**
      An adapter is an object that receives requests from a store and
      translates them into the appropriate action to take against your
      persistence layer. The persistence layer is usually an HTTP API, but
      may be anything, such as the browser's local storage. Typically the
      adapter is not invoked directly instead its functionality is accessed
      through the `store`.

      ### Creating an Adapter

      Create a new subclass of `DS.Adapter`, then assign
      it to the `ApplicationAdapter` property of the application.

      ```javascript
      var MyAdapter = DS.Adapter.extend({
        // ...your code here
      });

      App.ApplicationAdapter = MyAdapter;
      ```

      Model-specific adapters can be created by assigning your adapter
      class to the `ModelName` + `Adapter` property of the application.

      ```javascript
      var MyPostAdapter = DS.Adapter.extend({
        // ...Post-specific adapter code goes here
      });

      App.PostAdapter = MyPostAdapter;
      ```

      `DS.Adapter` is an abstract base class that you should override in your
      application to customize it for your backend. The minimum set of methods
      that you should implement is:

        * `find()`
        * `createRecord()`
        * `updateRecord()`
        * `deleteRecord()`
        * `findAll()`
        * `findQuery()`

      To improve the network performance of your application, you can optimize
      your adapter by overriding these lower-level methods:

        * `findMany()`


      For an example implementation, see `DS.RESTAdapter`, the
      included REST adapter.

      @class Adapter
      @namespace DS
      @extends Ember.Object
    */

    var Adapter = Ember.Object.extend({

      /**
        If you would like your adapter to use a custom serializer you can
        set the `defaultSerializer` property to be the name of the custom
        serializer.

        Note the `defaultSerializer` serializer has a lower priority then
        a model specific serializer (i.e. `PostSerializer`) or the
        `application` serializer.

        ```javascript
        var DjangoAdapter = DS.Adapter.extend({
          defaultSerializer: 'django'
        });
        ```

        @property defaultSerializer
        @type {String}
      */

      /**
        The `find()` method is invoked when the store is asked for a record that
        has not previously been loaded. In response to `find()` being called, you
        should query your persistence layer for a record with the given ID. Once
        found, you can asynchronously call the store's `push()` method to push
        the record into the store.

        Here is an example `find` implementation:

        ```javascript
        App.ApplicationAdapter = DS.Adapter.extend({
          find: function(store, type, id) {
            var url = [type, id].join('/');

            return new Ember.RSVP.Promise(function(resolve, reject) {
              jQuery.getJSON(url).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 find
        @param {DS.Store} store
        @param {subclass of DS.Model} type
        @param {String} id
        @return {Promise} promise
      */
      find: Ember.required(Function),

      /**
        The `findAll()` method is called when you call `find` on the store
        without an ID (i.e. `store.find('post')`).

        Example

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

        @private
        @method findAll
        @param {DS.Store} store
        @param {subclass of DS.Model} type
        @param {String} sinceToken
        @return {Promise} promise
      */
      findAll: null,

      /**
        This method is called when you call `find` on the store with a
        query object as the second parameter (i.e. `store.find('person', {
        page: 1 })`).

        Example

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

        @private
        @method findQuery
        @param {DS.Store} store
        @param {subclass of DS.Model} type
        @param {Object} query
        @param {DS.AdapterPopulatedRecordArray} recordArray
        @return {Promise} promise
      */
      findQuery: null,

      /**
        If the globally unique IDs for your records should be generated on the client,
        implement the `generateIdForRecord()` method. This method will be invoked
        each time you create a new record, and the value returned from it will be
        assigned to the record's `primaryKey`.

        Most traditional REST-like HTTP APIs will not use this method. Instead, the ID
        of the record will be set by the server, and your adapter will update the store
        with the new ID when it calls `didCreateRecord()`. Only implement this method if
        you intend to generate record IDs on the client-side.

        The `generateIdForRecord()` method will be invoked with the requesting store as
        the first parameter and the newly created record as the second parameter:

        ```javascript
        generateIdForRecord: function(store, record) {
          var uuid = App.generateUUIDWithStatisticallyLowOddsOfCollision();
          return uuid;
        }
        ```

        @method generateIdForRecord
        @param {DS.Store} store
        @param {DS.Model} record
        @return {String|Number} id
      */
      generateIdForRecord: null,

      /**
        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
      */
      serialize: function(record, options) {
        return get(record, 'store').serializerFor(record.constructor.typeKey).serialize(record, options);
      },

      /**
        Implement this method in a subclass to handle the creation of
        new records.

        Serializes the record and send it to the server.

        Example

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

            return new Ember.RSVP.Promise(function(resolve, reject) {
              jQuery.ajax({
                type: 'POST',
                url: url,
                dataType: 'json',
                data: data
              }).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 createRecord
        @param {DS.Store} store
        @param {subclass of DS.Model} type   the DS.Model class of the record
        @param {DS.Model} record
        @return {Promise} promise
      */
      createRecord: Ember.required(Function),

      /**
        Implement this method in a subclass to handle the updating of
        a record.

        Serializes the record update and send it to the server.

        Example

        ```javascript
        App.ApplicationAdapter = DS.Adapter.extend({
          updateRecord: function(store, type, record) {
            var data = this.serialize(record, { includeId: true });
            var id = record.get('id');
            var url = [type, id].join('/');

            return new Ember.RSVP.Promise(function(resolve, reject) {
              jQuery.ajax({
                type: 'PUT',
                url: url,
                dataType: 'json',
                data: data
              }).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 updateRecord
        @param {DS.Store} store
        @param {subclass of DS.Model} type   the DS.Model class of the record
        @param {DS.Model} record
        @return {Promise} promise
      */
      updateRecord: Ember.required(Function),

      /**
        Implement this method in a subclass to handle the deletion of
        a record.

        Sends a delete request for the record to the server.

        Example

        ```javascript
        App.ApplicationAdapter = DS.Adapter.extend({
          deleteRecord: function(store, type, record) {
            var data = this.serialize(record, { includeId: true });
            var id = record.get('id');
            var url = [type, id].join('/');

            return new Ember.RSVP.Promise(function(resolve, reject) {
              jQuery.ajax({
                type: 'DELETE',
                url: url,
                dataType: 'json',
                data: data
              }).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 deleteRecord
        @param {DS.Store} store
        @param {subclass of DS.Model} type   the DS.Model class of the record
        @param {DS.Model} record
        @return {Promise} promise
      */
      deleteRecord: Ember.required(Function),

      /**
        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
      */
      findMany: function(store, type, ids) {
        var promises = map.call(ids, function(id) {
          return this.find(store, type, id);
        }, this);

        return Ember.RSVP.all(promises);
      }
    });

    __exports__.InvalidError = InvalidError;
    __exports__.Adapter = Adapter;
    __exports__["default"] = Adapter;
  });
define("ember-data/lib/system/changes", 
  ["./changes/relationship_change","exports"],
  function(__dependency1__, __exports__) {
    "use strict";
    /**
      @module ember-data
    */

    var RelationshipChange = __dependency1__.RelationshipChange;
    var RelationshipChangeAdd = __dependency1__.RelationshipChangeAdd;
    var RelationshipChangeRemove = __dependency1__.RelationshipChangeRemove;
    var OneToManyChange = __dependency1__.OneToManyChange;
    var ManyToNoneChange = __dependency1__.ManyToNoneChange;
    var OneToOneChange = __dependency1__.OneToOneChange;
    var ManyToManyChange = __dependency1__.ManyToManyChange;

    __exports__.RelationshipChange = RelationshipChange;
    __exports__.RelationshipChangeAdd = RelationshipChangeAdd;
    __exports__.RelationshipChangeRemove = RelationshipChangeRemove;
    __exports__.OneToManyChange = OneToManyChange;
    __exports__.ManyToNoneChange = ManyToNoneChange;
    __exports__.OneToOneChange = OneToOneChange;
    __exports__.ManyToManyChange = ManyToManyChange;
  });
define("ember-data/lib/system/changes/relationship_change", 
  ["../model","exports"],
  function(__dependency1__, __exports__) {
    "use strict";
    /**
      @module ember-data
    */

    var Model = __dependency1__.Model;

    var get = Ember.get, set = Ember.set;
    var forEach = Ember.EnumerableUtils.forEach;

    /**
      @class RelationshipChange
      @namespace DS
      @private
      @constructor
    */
    var RelationshipChange = function(options) {
      this.parentRecord = options.parentRecord;
      this.childRecord = options.childRecord;
      this.firstRecord = options.firstRecord;
      this.firstRecordKind = options.firstRecordKind;
      this.firstRecordName = options.firstRecordName;
      this.secondRecord = options.secondRecord;
      this.secondRecordKind = options.secondRecordKind;
      this.secondRecordName = options.secondRecordName;
      this.changeType = options.changeType;
      this.store = options.store;

      this.committed = {};
    };

    /**
      @class RelationshipChangeAdd
      @namespace DS
      @private
      @constructor
    */
    var RelationshipChangeAdd = function(options){
      RelationshipChange.call(this, options);
    };

    /**
      @class RelationshipChangeRemove
      @namespace DS
      @private
      @constructor
    */
    var RelationshipChangeRemove = function(options){
      RelationshipChange.call(this, options);
    };

    RelationshipChange.create = function(options) {
      return new RelationshipChange(options);
    };

    RelationshipChangeAdd.create = function(options) {
      return new RelationshipChangeAdd(options);
    };

    RelationshipChangeRemove.create = function(options) {
      return new RelationshipChangeRemove(options);
    };

    var OneToManyChange = {};
    var OneToNoneChange = {};
    var ManyToNoneChange = {};
    var OneToOneChange = {};
    var ManyToManyChange = {};

    RelationshipChange._createChange = function(options){
      if(options.changeType === "add"){
        return RelationshipChangeAdd.create(options);
      }
      if(options.changeType === "remove"){
        return RelationshipChangeRemove.create(options);
      }
    };


    RelationshipChange.determineRelationshipType = function(recordType, knownSide){
      var knownKey = knownSide.key, key, otherKind;
      var knownKind = knownSide.kind;

      var inverse = recordType.inverseFor(knownKey);

      if (inverse){
        key = inverse.name;
        otherKind = inverse.kind;
      }

      if (!inverse){
        return knownKind === "belongsTo" ? "oneToNone" : "manyToNone";
      }
      else{
        if(otherKind === "belongsTo"){
          return knownKind === "belongsTo" ? "oneToOne" : "manyToOne";
        }
        else{
          return knownKind === "belongsTo" ? "oneToMany" : "manyToMany";
        }
      }

    };

    RelationshipChange.createChange = function(firstRecord, secondRecord, store, options){
      // Get the type of the child based on the child's client ID
      var firstRecordType = firstRecord.constructor, changeType;
      changeType = RelationshipChange.determineRelationshipType(firstRecordType, options);
      if (changeType === "oneToMany"){
        return OneToManyChange.createChange(firstRecord, secondRecord, store, options);
      }
      else if (changeType === "manyToOne"){
        return OneToManyChange.createChange(secondRecord, firstRecord, store, options);
      }
      else if (changeType === "oneToNone"){
        return OneToNoneChange.createChange(firstRecord, secondRecord, store, options);
      }
      else if (changeType === "manyToNone"){
        return ManyToNoneChange.createChange(firstRecord, secondRecord, store, options);
      }
      else if (changeType === "oneToOne"){
        return OneToOneChange.createChange(firstRecord, secondRecord, store, options);
      }
      else if (changeType === "manyToMany"){
        return ManyToManyChange.createChange(firstRecord, secondRecord, store, options);
      }
    };

    OneToNoneChange.createChange = function(childRecord, parentRecord, store, options) {
      var key = options.key;
      var change = RelationshipChange._createChange({
          parentRecord: parentRecord,
          childRecord: childRecord,
          firstRecord: childRecord,
          store: store,
          changeType: options.changeType,
          firstRecordName: key,
          firstRecordKind: "belongsTo"
      });

      store.addRelationshipChangeFor(childRecord, key, parentRecord, null, change);

      return change;
    };

    ManyToNoneChange.createChange = function(childRecord, parentRecord, store, options) {
      var key = options.key;
      var change = RelationshipChange._createChange({
          parentRecord: childRecord,
          childRecord: parentRecord,
          secondRecord: childRecord,
          store: store,
          changeType: options.changeType,
          secondRecordName: options.key,
          secondRecordKind: "hasMany"
      });

      store.addRelationshipChangeFor(childRecord, key, parentRecord, null, change);
      return change;
    };


    ManyToManyChange.createChange = function(childRecord, parentRecord, store, options) {
      // If the name of the belongsTo side of the relationship is specified,
      // use that
      // If the type of the parent is specified, look it up on the child's type
      // definition.
      var key = options.key;

      var change = RelationshipChange._createChange({
          parentRecord: parentRecord,
          childRecord: childRecord,
          firstRecord: childRecord,
          secondRecord: parentRecord,
          firstRecordKind: "hasMany",
          secondRecordKind: "hasMany",
          store: store,
          changeType: options.changeType,
          firstRecordName:  key
      });

      store.addRelationshipChangeFor(childRecord, key, parentRecord, null, change);


      return change;
    };

    OneToOneChange.createChange = function(childRecord, parentRecord, store, options) {
      var key;

      // If the name of the belongsTo side of the relationship is specified,
      // use that
      // If the type of the parent is specified, look it up on the child's type
      // definition.
      if (options.parentType) {
        key = options.parentType.inverseFor(options.key).name;
      } else if (options.key) {
        key = options.key;
      } else {
        Ember.assert("You must pass either a parentType or belongsToName option to OneToManyChange.forChildAndParent", false);
      }

      var change = RelationshipChange._createChange({
          parentRecord: parentRecord,
          childRecord: childRecord,
          firstRecord: childRecord,
          secondRecord: parentRecord,
          firstRecordKind: "belongsTo",
          secondRecordKind: "belongsTo",
          store: store,
          changeType: options.changeType,
          firstRecordName:  key
      });

      store.addRelationshipChangeFor(childRecord, key, parentRecord, null, change);


      return change;
    };

    OneToOneChange.maintainInvariant = function(options, store, childRecord, key){
      if (options.changeType === "add" && store.recordIsMaterialized(childRecord)) {
        var oldParent = get(childRecord, key);
        if (oldParent){
          var correspondingChange = OneToOneChange.createChange(childRecord, oldParent, store, {
              parentType: options.parentType,
              hasManyName: options.hasManyName,
              changeType: "remove",
              key: options.key
            });
          store.addRelationshipChangeFor(childRecord, key, options.parentRecord , null, correspondingChange);
         correspondingChange.sync();
        }
      }
    };

    OneToManyChange.createChange = function(childRecord, parentRecord, store, options) {
      var key;

      // If the name of the belongsTo side of the relationship is specified,
      // use that
      // If the type of the parent is specified, look it up on the child's type
      // definition.
      if (options.parentType) {
        key = options.parentType.inverseFor(options.key).name;
        OneToManyChange.maintainInvariant( options, store, childRecord, key );
      } else if (options.key) {
        key = options.key;
      } else {
        Ember.assert("You must pass either a parentType or belongsToName option to OneToManyChange.forChildAndParent", false);
      }

      var change = RelationshipChange._createChange({
          parentRecord: parentRecord,
          childRecord: childRecord,
          firstRecord: childRecord,
          secondRecord: parentRecord,
          firstRecordKind: "belongsTo",
          secondRecordKind: "hasMany",
          store: store,
          changeType: options.changeType,
          firstRecordName:  key
      });

      store.addRelationshipChangeFor(childRecord, key, parentRecord, change.getSecondRecordName(), change);


      return change;
    };


    OneToManyChange.maintainInvariant = function(options, store, childRecord, key){
      if (options.changeType === "add" && childRecord) {
        var oldParent = get(childRecord, key);
        if (oldParent){
          var correspondingChange = OneToManyChange.createChange(childRecord, oldParent, store, {
              parentType: options.parentType,
              hasManyName: options.hasManyName,
              changeType: "remove",
              key: options.key
            });
          store.addRelationshipChangeFor(childRecord, key, options.parentRecord, correspondingChange.getSecondRecordName(), correspondingChange);
          correspondingChange.sync();
        }
      }
    };

    /**
      @class RelationshipChange
      @namespace DS
    */
    RelationshipChange.prototype = {

      getSecondRecordName: function() {
        var name = this.secondRecordName, parent;

        if (!name) {
          parent = this.secondRecord;
          if (!parent) { return; }

          var childType = this.firstRecord.constructor;
          var inverse = childType.inverseFor(this.firstRecordName);
          this.secondRecordName = inverse.name;
        }

        return this.secondRecordName;
      },

      /**
        Get the name of the relationship on the belongsTo side.

        @method getFirstRecordName
        @return {String}
      */
      getFirstRecordName: function() {
        var name = this.firstRecordName;
        return name;
      },

      /**
        @method destroy
        @private
      */
      destroy: function() {
        var childRecord = this.childRecord,
            belongsToName = this.getFirstRecordName(),
            hasManyName = this.getSecondRecordName(),
            store = this.store;

        store.removeRelationshipChangeFor(childRecord, belongsToName, this.parentRecord, hasManyName, this.changeType);
      },

      getSecondRecord: function(){
        return this.secondRecord;
      },

      /**
        @method getFirstRecord
        @private
      */
      getFirstRecord: function() {
        return this.firstRecord;
      },

      coalesce: function(){
        var relationshipPairs = this.store.relationshipChangePairsFor(this.firstRecord);
        forEach(relationshipPairs, function(pair){
          var addedChange = pair["add"];
          var removedChange = pair["remove"];
          if(addedChange && removedChange) {
            addedChange.destroy();
            removedChange.destroy();
          }
        });
      }
    };

    RelationshipChangeAdd.prototype = Ember.create(RelationshipChange.create({}));
    RelationshipChangeRemove.prototype = Ember.create(RelationshipChange.create({}));

    // the object is a value, and not a promise
    function isValue(object) {
      return typeof object === 'object' && (!object.then || typeof object.then !== 'function');
    }

    RelationshipChangeAdd.prototype.changeType = "add";
    RelationshipChangeAdd.prototype.sync = function() {
      var secondRecordName = this.getSecondRecordName(),
          firstRecordName = this.getFirstRecordName(),
          firstRecord = this.getFirstRecord(),
          secondRecord = this.getSecondRecord();

      //Ember.assert("You specified a hasMany (" + hasManyName + ") on " + (!belongsToName && (newParent || oldParent || this.lastParent).constructor) + " but did not specify an inverse belongsTo on " + child.constructor, belongsToName);
      //Ember.assert("You specified a belongsTo (" + belongsToName + ") on " + child.constructor + " but did not specify an inverse hasMany on " + (!hasManyName && (newParent || oldParent || this.lastParentRecord).constructor), hasManyName);

      if (secondRecord instanceof Model && firstRecord instanceof Model) {
        if(this.secondRecordKind === "belongsTo"){
          secondRecord.suspendRelationshipObservers(function(){
            set(secondRecord, secondRecordName, firstRecord);
          });

         }
         else if(this.secondRecordKind === "hasMany"){
          secondRecord.suspendRelationshipObservers(function(){
            var relationship = get(secondRecord, secondRecordName);
            if (isValue(relationship)) { relationship.addObject(firstRecord); }
          });
        }
      }

      if (firstRecord instanceof Model && secondRecord instanceof Model && get(firstRecord, firstRecordName) !== secondRecord) {
        if(this.firstRecordKind === "belongsTo"){
          firstRecord.suspendRelationshipObservers(function(){
            set(firstRecord, firstRecordName, secondRecord);
          });
        }
        else if(this.firstRecordKind === "hasMany"){
          firstRecord.suspendRelationshipObservers(function(){
            var relationship = get(firstRecord, firstRecordName);
            if (isValue(relationship)) { relationship.addObject(secondRecord); }
          });
        }
      }

      this.coalesce();
    };

    RelationshipChangeRemove.prototype.changeType = "remove";
    RelationshipChangeRemove.prototype.sync = function() {
      var secondRecordName = this.getSecondRecordName(),
          firstRecordName = this.getFirstRecordName(),
          firstRecord = this.getFirstRecord(),
          secondRecord = this.getSecondRecord();

      //Ember.assert("You specified a hasMany (" + hasManyName + ") on " + (!belongsToName && (newParent || oldParent || this.lastParent).constructor) + " but did not specify an inverse belongsTo on " + child.constructor, belongsToName);
      //Ember.assert("You specified a belongsTo (" + belongsToName + ") on " + child.constructor + " but did not specify an inverse hasMany on " + (!hasManyName && (newParent || oldParent || this.lastParentRecord).constructor), hasManyName);

      if (secondRecord instanceof Model && firstRecord instanceof Model) {
        if(this.secondRecordKind === "belongsTo"){
          secondRecord.suspendRelationshipObservers(function(){
            set(secondRecord, secondRecordName, null);
          });
        }
        else if(this.secondRecordKind === "hasMany"){
          secondRecord.suspendRelationshipObservers(function(){
            var relationship = get(secondRecord, secondRecordName);
            if (isValue(relationship)) { relationship.removeObject(firstRecord); }
          });
        }
      }

      if (firstRecord instanceof Model && get(firstRecord, firstRecordName)) {
        if(this.firstRecordKind === "belongsTo"){
          firstRecord.suspendRelationshipObservers(function(){
            set(firstRecord, firstRecordName, null);
          });
         }
         else if(this.firstRecordKind === "hasMany"){
           firstRecord.suspendRelationshipObservers(function(){
             var relationship = get(firstRecord, firstRecordName);
             if (isValue(relationship)) { relationship.removeObject(secondRecord); }
          });
        }
      }

      this.coalesce();
    };

    __exports__.RelationshipChange = RelationshipChange;
    __exports__.RelationshipChangeAdd = RelationshipChangeAdd;
    __exports__.RelationshipChangeRemove = RelationshipChangeRemove;
    __exports__.OneToManyChange = OneToManyChange;
    __exports__.ManyToNoneChange = ManyToNoneChange;
    __exports__.OneToOneChange = OneToOneChange;
    __exports__.ManyToManyChange = ManyToManyChange;
  });
define("ember-data/lib/system/container_proxy", 
  ["exports"],
  function(__exports__) {
    "use strict";
    /**
      This is used internally to enable deprecation of container paths and provide
      a decent message to the user indicating how to fix the issue.

      @class ContainerProxy
      @namespace DS
      @private
    */
    var ContainerProxy = function (container){
      this.container = container;
    };

    ContainerProxy.prototype.aliasedFactory = function(path, preLookup) {
      var _this = this;

      return {create: function(){ 
        if (preLookup) { preLookup(); }

        return _this.container.lookup(path); 
      }};
    };

    ContainerProxy.prototype.registerAlias = function(source, dest, preLookup) {
      var factory = this.aliasedFactory(dest, preLookup);

      return this.container.register(source, factory);
    };

    ContainerProxy.prototype.registerDeprecation = function(deprecated, valid) {
      var preLookupCallback = function(){
        Ember.deprecate("You tried to look up '" + deprecated + "', " +
                        "but this has been deprecated in favor of '" + valid + "'.", false);
      };

      return this.registerAlias(deprecated, valid, preLookupCallback);
    };

    ContainerProxy.prototype.registerDeprecations = function(proxyPairs) {
      for (var i = proxyPairs.length; i > 0; i--) {
        var proxyPair = proxyPairs[i - 1],
            deprecated = proxyPair['deprecated'],
            valid = proxyPair['valid'];

        this.registerDeprecation(deprecated, valid);
      }
    };

    __exports__["default"] = ContainerProxy;
  });
define("ember-data/lib/system/debug", 
  ["./debug/debug_info","./debug/debug_adapter","exports"],
  function(__dependency1__, __dependency2__, __exports__) {
    "use strict";
    /**
      @module ember-data
    */

    var DebugAdapter = __dependency2__["default"];

    __exports__["default"] = DebugAdapter;
  });
define("ember-data/lib/system/debug/debug_adapter", 
  ["../model","exports"],
  function(__dependency1__, __exports__) {
    "use strict";
    /**
      @module ember-data
    */
    var Model = __dependency1__.Model;
    var get = Ember.get, capitalize = Ember.String.capitalize, underscore = Ember.String.underscore;

    /**
      Extend `Ember.DataAdapter` with ED specific code.

      @class DebugAdapter
      @namespace DS
      @extends Ember.DataAdapter
      @private
    */
    var DebugAdapter = Ember.DataAdapter.extend({
      getFilters: function() {
        return [
          { name: 'isNew', desc: 'New' },
          { name: 'isModified', desc: 'Modified' },
          { name: 'isClean', desc: 'Clean' }
        ];
      },

      detect: function(klass) {
        return klass !== Model && Model.detect(klass);
      },

      columnsForType: function(type) {
        var columns = [{ name: 'id', desc: 'Id' }], count = 0, self = this;
        get(type, 'attributes').forEach(function(name, meta) {
            if (count++ > self.attributeLimit) { return false; }
            var desc = capitalize(underscore(name).replace('_', ' '));
            columns.push({ name: name, desc: desc });
        });
        return columns;
      },

      getRecords: function(type) {
        return this.get('store').all(type);
      },

      getRecordColumnValues: function(record) {
        var self = this, count = 0,
            columnValues = { id: get(record, 'id') };

        record.eachAttribute(function(key) {
          if (count++ > self.attributeLimit) {
            return false;
          }
          var value = get(record, key);
          columnValues[key] = value;
        });
        return columnValues;
      },

      getRecordKeywords: function(record) {
        var keywords = [], keys = Ember.A(['id']);
        record.eachAttribute(function(key) {
          keys.push(key);
        });
        keys.forEach(function(key) {
          keywords.push(get(record, key));
        });
        return keywords;
      },

      getRecordFilterValues: function(record) {
        return {
          isNew: record.get('isNew'),
          isModified: record.get('isDirty') && !record.get('isNew'),
          isClean: !record.get('isDirty')
        };
      },

      getRecordColor: function(record) {
        var color = 'black';
        if (record.get('isNew')) {
          color = 'green';
        } else if (record.get('isDirty')) {
          color = 'blue';
        }
        return color;
      },

      observeRecord: function(record, recordUpdated) {
        var releaseMethods = Ember.A(), self = this,
            keysToObserve = Ember.A(['id', 'isNew', 'isDirty']);

        record.eachAttribute(function(key) {
          keysToObserve.push(key);
        });

        keysToObserve.forEach(function(key) {
          var handler = function() {
            recordUpdated(self.wrapRecord(record));
          };
          Ember.addObserver(record, key, handler);
          releaseMethods.push(function() {
            Ember.removeObserver(record, key, handler);
          });
        });

        var release = function() {
          releaseMethods.forEach(function(fn) { fn(); } );
        };

        return release;
      }

    });

    __exports__["default"] = DebugAdapter;
  });
define("ember-data/lib/system/debug/debug_info", 
  ["../model","exports"],
  function(__dependency1__, __exports__) {
    "use strict";
    var Model = __dependency1__.Model;

    Model.reopen({

      /**
        Provides info about the model for debugging purposes
        by grouping the properties into more semantic groups.

        Meant to be used by debugging tools such as the Chrome Ember Extension.

        - Groups all attributes in "Attributes" group.
        - Groups all belongsTo relationships in "Belongs To" group.
        - Groups all hasMany relationships in "Has Many" group.
        - Groups all flags in "Flags" group.
        - Flags relationship CPs as expensive properties.

        @method _debugInfo
        @for DS.Model
        @private
      */
      _debugInfo: function() {
        var attributes = ['id'],
            relationships = { belongsTo: [], hasMany: [] },
            expensiveProperties = [];

        this.eachAttribute(function(name, meta) {
          attributes.push(name);
        }, this);

        this.eachRelationship(function(name, relationship) {
          relationships[relationship.kind].push(name);
          expensiveProperties.push(name);
        });

        var groups = [
          {
            name: 'Attributes',
            properties: attributes,
            expand: true
          },
          {
            name: 'Belongs To',
            properties: relationships.belongsTo,
            expand: true
          },
          {
            name: 'Has Many',
            properties: relationships.hasMany,
            expand: true
          },
          {
            name: 'Flags',
            properties: ['isLoaded', 'isDirty', 'isSaving', 'isDeleted', 'isError', 'isNew', 'isValid']
          }
        ];

        return {
          propertyInfo: {
            // include all other mixins / properties (not just the grouped ones)
            includeOtherProperties: true,
            groups: groups,
            // don't pre-calculate unless cached
            expensiveProperties: expensiveProperties
          }
        };
      }
    });

    __exports__["default"] = Model;
  });
define("ember-data/lib/system/model", 
  ["./model/model","./model/attributes","./model/states","./model/errors","exports"],
  function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
    "use strict";
    /**
      @module ember-data
    */

    var Model = __dependency1__["default"];
    var attr = __dependency2__["default"];
    var RootState = __dependency3__["default"];
    var Errors = __dependency4__["default"];

    __exports__.Model = Model;
    __exports__.RootState = RootState;
    __exports__.attr = attr;
    __exports__.Errors = Errors;
  });
define("ember-data/lib/system/model/attributes", 
  ["./model","exports"],
  function(__dependency1__, __exports__) {
    "use strict";
    var Model = __dependency1__["default"];

    /**
      @module ember-data
    */

    var get = Ember.get;

    /**
      @class Model
      @namespace DS
    */
    Model.reopenClass({
      /**
        A map whose keys are the attributes of the model (properties
        described by DS.attr) and whose values are the meta object for the
        property.

        Example

        ```javascript

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

        var attributes = Ember.get(App.Person, 'attributes')

        attributes.forEach(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"}
        ```

        @property attributes
        @static
        @type {Ember.Map}
        @readOnly
      */
      attributes: Ember.computed(function() {
        var map = Ember.Map.create();

        this.eachComputedProperty(function(name, meta) {
          if (meta.isAttribute) {
            Ember.assert("You may not set `id` as an attribute on your model. Please remove any lines that look like: `id: DS.attr('<type>')` from " + this.toString(), name !== 'id');

            meta.name = name;
            map.set(name, meta);
          }
        });

        return map;
      }),

      /**
        A map whose keys are the attributes of the model (properties
        described by DS.attr) and whose values are type of transformation
        applied to each attribute. This map does not include any
        attributes that do not have an transformation type.

        Example

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

        var transformedAttributes = Ember.get(App.Person, 'transformedAttributes')

        transformedAttributes.forEach(function(field, type) {
          console.log(field, type);
        });

        // prints:
        // lastName string
        // birthday date
        ```

        @property transformedAttributes
        @static
        @type {Ember.Map}
        @readOnly
      */
      transformedAttributes: Ember.computed(function() {
        var map = Ember.Map.create();

        this.eachAttribute(function(key, meta) {
          if (meta.type) {
            map.set(key, meta.type);
          }
        });

        return map;
      }),

      /**
        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
      */
      eachAttribute: function(callback, binding) {
        get(this, 'attributes').forEach(function(name, meta) {
          callback.call(binding, name, meta);
        }, binding);
      },

      /**
        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 string containing 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
      */
      eachTransformedAttribute: function(callback, binding) {
        get(this, 'transformedAttributes').forEach(function(name, type) {
          callback.call(binding, name, type);
        });
      }
    });


    Model.reopen({
      eachAttribute: function(callback, binding) {
        this.constructor.eachAttribute(callback, binding);
      }
    });

    function getDefaultValue(record, options, key) {
      if (typeof options.defaultValue === "function") {
        return options.defaultValue.apply(null, arguments);
      } else {
        return options.defaultValue;
      }
    }

    function hasValue(record, key) {
      return record._attributes.hasOwnProperty(key) ||
             record._inFlightAttributes.hasOwnProperty(key) ||
             record._data.hasOwnProperty(key);
    }

    function getValue(record, key) {
      if (record._attributes.hasOwnProperty(key)) {
        return record._attributes[key];
      } else if (record._inFlightAttributes.hasOwnProperty(key)) {
        return record._inFlightAttributes[key];
      } else {
        return record._data[key];
      }
    }

    /**
      `DS.attr` defines an attribute on a [DS.Model](/api/data/classes/DS.Model.html).
      By default, attributes are passed through as-is, however you can specify an
      optional type to have the value automatically transformed.
      Ember Data ships with four basic transform types: `string`, `number`,
      `boolean` and `date`. You can define your own transforms by subclassing
      [DS.Transform](/api/data/classes/DS.Transform.html).

      Note that you cannot use `attr` to define an attribute of `id`.

      `DS.attr` takes an optional hash as a second parameter, currently
      supported options are:

      - `defaultValue`: Pass a string or a function to be called to set the attribute
                        to a default value if none is supplied.

      Example

      ```javascript
      var attr = DS.attr;

      App.User = DS.Model.extend({
        username: attr('string'),
        email: attr('string'),
        verified: attr('boolean', {defaultValue: false})
      });
      ```

      @namespace
      @method attr
      @for DS
      @param {String} type the attribute type
      @param {Object} options a hash of options
      @return {Attribute}
    */

    function attr(type, options) {
      options = options || {};

      var meta = {
        type: type,
        isAttribute: true,
        options: options
      };

      return Ember.computed('data', function(key, value) {
        if (arguments.length > 1) {
          Ember.assert("You may not set `id` as an attribute on your model. Please remove any lines that look like: `id: DS.attr('<type>')` from " + this.constructor.toString(), key !== 'id');
          var oldValue = getValue(this, key);

          if (value !== oldValue) {
            // Add the new value to the changed attributes hash; it will get deleted by
            // the 'didSetProperty' handler if it is no different from the original value
            this._attributes[key] = value;

            this.send('didSetProperty', {
              name: key,
              oldValue: oldValue,
              originalValue: this._data[key],
              value: value
            });
          }

          return value;
        } else if (hasValue(this, key)) {
          return getValue(this, key);
        } else {
          return getDefaultValue(this, options, key);
        }

      // `data` is never set directly. However, it may be
      // invalidated from the state manager's setData
      // event.
      }).meta(meta);
    }

    __exports__["default"] = attr;
  });
define("ember-data/lib/system/model/errors", 
  ["exports"],
  function(__exports__) {
    "use strict";
    var get = Ember.get, isEmpty = Ember.isEmpty;
    var map = Ember.EnumerableUtils.map;

    /**
    @module ember-data
    */

    /**
      Holds validation errors for a given record organized by attribute names.

      Every DS.Model has an `errors` property that is an instance of
      `DS.Errors`. This can be used to display validation error
      messages returned from the server when a `record.save()` rejects.

      For Example, if you had an `User` model that looked like this:

      ```javascript
      App.User = DS.Model.extend({
        username: attr('string'),
        email: attr('string')
      });
      ```
      And you attempted to save a record that did not validate on the backend.

      ```javascript
      var user = store.createRecord('user', {
        username: 'tomster',
        email: 'invalidEmail'
      });
      user.save();
      ```

      Your backend data store might return a response that looks like
      this. This response will be used to populate the error object.

      ```javascript
      {
        "errors": {
          "username": ["This username is already taken!"],
          "email": ["Doesn't look like a valid email."]
        }
      }
      ```

      Errors can be displayed to the user by accessing their property name
      or using the `messages` property to get an array of all errors.

      ```handlebars
      {{#each errors.messages}}
        <div class="error">
          {{message}}
        </div>
      {{/each}}

      <label>Username: {{input value=username}} </label>
      {{#each errors.username}}
        <div class="error">
          {{message}}
        </div>
      {{/each}}

      <label>Email: {{input value=email}} </label>
      {{#each errors.email}}
        <div class="error">
          {{message}}
        </div>
      {{/each}}
      ```

      @class Errors
      @namespace DS
      @extends Ember.Object
      @uses Ember.Enumerable
      @uses Ember.Evented
     */
    var Errors = Ember.Object.extend(Ember.Enumerable, Ember.Evented, {
      /**
        Register with target handler

        @method registerHandlers
        @param {Object} target
        @param {Function} becameInvalid
        @param {Function} becameValid
      */
      registerHandlers: function(target, becameInvalid, becameValid) {
        this.on('becameInvalid', target, becameInvalid);
        this.on('becameValid', target, becameValid);
      },

      /**
        @property errorsByAttributeName
        @type {Ember.MapWithDefault}
        @private
      */
      errorsByAttributeName: Ember.reduceComputed("content", {
        initialValue: function() {
          return Ember.MapWithDefault.create({
            defaultValue: function() {
              return Ember.A();
            }
          });
        },

        addedItem: function(errors, error) {
          errors.get(error.attribute).pushObject(error);

          return errors;
        },

        removedItem: function(errors, error) {
          errors.get(error.attribute).removeObject(error);

          return errors;
        }
      }),

      /**
        Returns errors for a given attribute

        ```javascript
        var user = store.createRecord('user', {
          username: 'tomster',
          email: 'invalidEmail'
        });
        user.save().catch(function(){
          user.get('errors').errorsFor('email'); // ["Doesn't look like a valid email."]
        });
        ```

        @method errorsFor
        @param {String} attribute
        @return {Array}
      */
      errorsFor: function(attribute) {
        return get(this, 'errorsByAttributeName').get(attribute);
      },

      /**
        An array containing all of the error messages for this
        record. This is useful for displaying all errors to the user.

        ```handlebars
        {{#each errors.messages}}
          <div class="error">
            {{message}}
          </div>
        {{/each}}
        ```

        @property messages
        @type {Array}
      */
      messages: Ember.computed.mapBy('content', 'message'),

      /**
        @property content
        @type {Array}
        @private
      */
      content: Ember.computed(function() {
        return Ember.A();
      }),

      /**
        @method unknownProperty
        @private
      */
      unknownProperty: function(attribute) {
        var errors = this.errorsFor(attribute);
        if (isEmpty(errors)) { return null; }
        return errors;
      },

      /**
        @method nextObject
        @private
      */
      nextObject: function(index, previousObject, context) {
        return get(this, 'content').objectAt(index);
      },

      /**
        Total number of errors.

        @property length
        @type {Number}
        @readOnly
      */
      length: Ember.computed.oneWay('content.length').readOnly(),

      /**
        @property isEmpty
        @type {Boolean}
        @readOnly
      */
      isEmpty: Ember.computed.not('length').readOnly(),

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

        Example:

        ```javascript
        if (!user.get('username') {
          user.get('errors').add('username', 'This field is required');
        }
        ```

        @method add
        @param {String} attribute
        @param {Array|String} messages
      */
      add: 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');
        }
      },

      /**
        @method _findOrCreateMessages
        @private
      */
      _findOrCreateMessages: function(attribute, messages) {
        var errors = this.errorsFor(attribute);

        return map(Ember.makeArray(messages), function(message) {
          return errors.findBy('message', message) || {
            attribute: attribute,
            message: message
          };
        });
      },

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

        Example:

        ```javascript
        App.User = DS.Model.extend({
          email: DS.attr('string'),
          twoFactorAuth: DS.attr('boolean'),
          phone: DS.attr('string')
        });

        App.UserEditRoute = Ember.Route.extend({
          actions: {
            save: function(user) {
               if (!user.get('twoFactorAuth')) {
                 user.get('errors').remove('phone');
               }
               user.save();
             }
          }
        });
        ```

        @method remove
        @param {String} attribute
      */
      remove: 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 and sends `becameValid` event
        to the record.

        Example:

        ```javascript
        App.UserEditRoute = Ember.Route.extend({
          actions: {
            retrySave: function(user) {
               user.get('errors').clear();
               user.save();
             }
          }
        });
        ```

        @method clear
      */
      clear: function() {
        if (get(this, 'isEmpty')) { return; }

        get(this, 'content').clear();
        this.enumerableContentDidChange();

        this.trigger('becameValid');
      },

      /**
        Checks if there is error messages for the given attribute.

        ```javascript
        App.UserEditRoute = Ember.Route.extend({
          actions: {
            save: function(user) {
               if (user.get('errors').has('email')) {
                 return alert('Please update your email before attempting to save.');
               }
               user.save();
             }
          }
        });
        ```

        @method has
        @param {String} attribute
        @return {Boolean} true if there some errors on given attribute
      */
      has: function(attribute) {
        return !isEmpty(this.errorsFor(attribute));
      }
    });

    __exports__["default"] = Errors;
  });
define("ember-data/lib/system/model/model", 
  ["./states","./errors","../store","exports"],
  function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
    "use strict";
    var RootState = __dependency1__["default"];
    var Errors = __dependency2__["default"];
    var PromiseObject = __dependency3__.PromiseObject;
    /**
      @module ember-data
    */

    var get = Ember.get, set = Ember.set,
        merge = Ember.merge,
        Promise = Ember.RSVP.Promise;

    var JSONSerializer;
    var retrieveFromCurrentState = Ember.computed('currentState', function(key, value) {
      return get(get(this, 'currentState'), key);
    }).readOnly();

    /**

      The model class that all Ember Data records descend from.

      @class Model
      @namespace DS
      @extends Ember.Object
      @uses Ember.Evented
    */
    var Model = Ember.Object.extend(Ember.Evented, {
      _recordArrays: undefined,
      _relationships: undefined,
      _loadingRecordArrays: undefined,
      /**
        If this property is `true` the record is in the `empty`
        state. Empty is the first state all records enter after they have
        been created. Most records created by the store will quickly
        transition to the `loading` state if data needs to be fetched from
        the server or the `created` state if the record is created on the
        client. A record can also enter the empty state if the adapter is
        unable to locate the record.

        @property isEmpty
        @type {Boolean}
        @readOnly
      */
      isEmpty: retrieveFromCurrentState,
      /**
        If this property is `true` the record is in the `loading` state. A
        record enters this state when the store asks the adapter for its
        data. It remains in this state until the adapter provides the
        requested data.

        @property isLoading
        @type {Boolean}
        @readOnly
      */
      isLoading: retrieveFromCurrentState,
      /**
        If this property is `true` the record is in the `loaded` state. A
        record enters this state when its data is populated. Most of a
        record's lifecycle is spent inside substates of the `loaded`
        state.

        Example

        ```javascript
        var record = store.createRecord('model');
        record.get('isLoaded'); // true

        store.find('model', 1).then(function(model) {
          model.get('isLoaded'); // true
        });
        ```

        @property isLoaded
        @type {Boolean}
        @readOnly
      */
      isLoaded: retrieveFromCurrentState,
      /**
        If this property is `true` the record is in the `dirty` state. The
        record has local changes that have not yet been saved by the
        adapter. This includes records that have been created (but not yet
        saved) or deleted.

        Example

        ```javascript
        var record = store.createRecord('model');
        record.get('isDirty'); // true

        store.find('model', 1).then(function(model) {
          model.get('isDirty'); // false
          model.set('foo', 'some value');
          model.get('isDirty'); // true
        });
        ```

        @property isDirty
        @type {Boolean}
        @readOnly
      */
      isDirty: retrieveFromCurrentState,
      /**
        If this property is `true` the record is in the `saving` state. A
        record enters the saving state when `save` is called, but the
        adapter has not yet acknowledged that the changes have been
        persisted to the backend.

        Example

        ```javascript
        var record = store.createRecord('model');
        record.get('isSaving'); // false
        var promise = record.save();
        record.get('isSaving'); // true
        promise.then(function() {
          record.get('isSaving'); // false
        });
        ```

        @property isSaving
        @type {Boolean}
        @readOnly
      */
      isSaving: retrieveFromCurrentState,
      /**
        If this property is `true` the record is in the `deleted` state
        and has been marked for deletion. When `isDeleted` is true and
        `isDirty` is true, the record is deleted locally but the deletion
        was not yet persisted. When `isSaving` is true, the change is
        in-flight. When both `isDirty` and `isSaving` are false, the
        change has persisted.

        Example

        ```javascript
        var record = store.createRecord('model');
        record.get('isDeleted');    // false
        record.deleteRecord();

        // Locally deleted
        record.get('isDeleted');    // true
        record.get('isDirty');      // true
        record.get('isSaving');     // false

        // Persisting the deletion
        var promise = record.save();
        record.get('isDeleted');    // true
        record.get('isSaving');     // true

        // Deletion Persisted
        promise.then(function() {
          record.get('isDeleted');  // true
          record.get('isSaving');   // false
          record.get('isDirty');    // false
        });
        ```

        @property isDeleted
        @type {Boolean}
        @readOnly
      */
      isDeleted: retrieveFromCurrentState,
      /**
        If this property is `true` the record is in the `new` state. A
        record will be in the `new` state when it has been created on the
        client and the adapter has not yet report that it was successfully
        saved.

        Example

        ```javascript
        var record = store.createRecord('model');
        record.get('isNew'); // true

        record.save().then(function(model) {
          model.get('isNew'); // false
        });
        ```

        @property isNew
        @type {Boolean}
        @readOnly
      */
      isNew: retrieveFromCurrentState,
      /**
        If this property is `true` the record is in the `valid` state.

        A record will be in the `valid` state when the adapter did not report any
        server-side validation failures.

        @property isValid
        @type {Boolean}
        @readOnly
      */
      isValid: retrieveFromCurrentState,
      /**
        If the record is in the dirty state this property will report what
        kind of change has caused it to move into the dirty
        state. Possible values are:

        - `created` The record has been created by the client and not yet saved to the adapter.
        - `updated` The record has been updated by the client and not yet saved to the adapter.
        - `deleted` The record has been deleted by the client and not yet saved to the adapter.

        Example

        ```javascript
        var record = store.createRecord('model');
        record.get('dirtyType'); // 'created'
        ```

        @property dirtyType
        @type {String}
        @readOnly
      */
      dirtyType: retrieveFromCurrentState,

      /**
        If `true` the adapter reported that it was unable to save local
        changes to the backend for any reason other than a server-side
        validation error.

        Example

        ```javascript
        record.get('isError'); // false
        record.set('foo', 'valid value');
        record.save().then(null, function() {
          record.get('isError'); // true
        });
        ```

        @property isError
        @type {Boolean}
        @readOnly
      */
      isError: false,
      /**
        If `true` the store is attempting to reload the record form the adapter.

        Example

        ```javascript
        record.get('isReloading'); // false
        record.reload();
        record.get('isReloading'); // true
        ```

        @property isReloading
        @type {Boolean}
        @readOnly
      */
      isReloading: false,

      /**
        The `clientId` property is a transient numerical identifier
        generated at runtime by the data store. It is important
        primarily because newly created objects may not yet have an
        externally generated id.

        @property clientId
        @private
        @type {Number|String}
      */
      clientId: null,
      /**
        All ember models have an id property. This is an identifier
        managed by an external source. These are always coerced to be
        strings before being used internally. Note when declaring the
        attributes for a model it is an error to declare an id
        attribute.

        ```javascript
        var record = store.createRecord('model');
        record.get('id'); // null

        store.find('model', 1).then(function(model) {
          model.get('id'); // '1'
        });
        ```

        @property id
        @type {String}
      */
      id: null,

      /**
        @property currentState
        @private
        @type {Object}
      */
      currentState: RootState.empty,

      /**
        When the record is in the `invalid` state this object will contain
        any errors returned by the adapter. When present the errors hash
        typically contains keys corresponding to the invalid property names
        and values which are an array of error messages.

        ```javascript
        record.get('errors.length'); // 0
        record.set('foo', 'invalid value');
        record.save().then(null, function() {
          record.get('errors').get('foo'); // ['foo should be a number.']
        });
        ```

        @property errors
        @type {DS.Errors}
      */
      errors: Ember.computed(function() {
        var errors = Errors.create();

        errors.registerHandlers(this, function() {
          this.send('becameInvalid');
        }, function() {
          this.send('becameValid');
        });

        return errors;
      }).readOnly(),

      /**
        Create a JSON representation of the record, using the serialization
        strategy of the store's adapter.

       `serialize` takes an optional hash as a parameter, currently
        supported options are:

       - `includeId`: `true` if the record's ID should be included in the
          JSON representation.

        @method serialize
        @param {Object} options
        @return {Object} an object whose values are primitive JSON values only
      */
      serialize: function(options) {
        var store = get(this, 'store');
        return store.serialize(this, options);
      },

      /**
        Use [DS.JSONSerializer](DS.JSONSerializer.html) to
        get the JSON representation of a record.

        `toJSON` takes an optional hash as a parameter, currently
        supported options are:

        - `includeId`: `true` if the record's ID should be included in the
          JSON representation.

        @method toJSON
        @param {Object} options
        @return {Object} A JSON representation of the object.
      */
      toJSON: function(options) {
        if (!JSONSerializer) { JSONSerializer = requireModule("ember-data/lib/serializers/json_serializer")["default"]; }
        // container is for lazy transform lookups
        var serializer = JSONSerializer.create({ container: this.container });
        return serializer.serialize(this, options);
      },

      /**
        Fired when the record is loaded from the server.

        @event didLoad
      */
      didLoad: Ember.K,

      /**
        Fired when the record is updated.

        @event didUpdate
      */
      didUpdate: Ember.K,

      /**
        Fired when the record is created.

        @event didCreate
      */
      didCreate: Ember.K,

      /**
        Fired when the record is deleted.

        @event didDelete
      */
      didDelete: Ember.K,

      /**
        Fired when the record becomes invalid.

        @event becameInvalid
      */
      becameInvalid: Ember.K,

      /**
        Fired when the record enters the error state.

        @event becameError
      */
      becameError: Ember.K,

      /**
        @property data
        @private
        @type {Object}
      */
      data: Ember.computed(function() {
        this._data = this._data || {};
        return this._data;
      }).readOnly(),

      _data: null,

      init: function() {
        this._super();
        this._setup();
      },

      _setup: function() {
        this._changesToSync = {};
        this._deferredTriggers = [];
        this._data = {};
        this._attributes = {};
        this._inFlightAttributes = {};
        this._relationships = {};
      },

      /**
        @method send
        @private
        @param {String} name
        @param {Object} context
      */
      send: function(name, context) {
        var currentState = get(this, 'currentState');

        if (!currentState[name]) {
          this._unhandledEvent(currentState, name, context);
        }

        return currentState[name](this, context);
      },

      /**
        @method transitionTo
        @private
        @param {String} name
      */
      transitionTo: function(name) {
        // POSSIBLE TODO: Remove this code and replace with
        // always having direct references to state objects

        var pivotName = name.split(".", 1),
            currentState = get(this, 'currentState'),
            state = currentState;

        do {
          if (state.exit) { state.exit(this); }
          state = state.parentState;
        } while (!state.hasOwnProperty(pivotName));

        var path = name.split(".");

        var setups = [], enters = [], i, l;

        for (i=0, l=path.length; i<l; i++) {
          state = state[path[i]];

          if (state.enter) { enters.push(state); }
          if (state.setup) { setups.push(state); }
        }

        for (i=0, l=enters.length; i<l; i++) {
          enters[i].enter(this);
        }

        set(this, 'currentState', state);

        for (i=0, l=setups.length; i<l; i++) {
          setups[i].setup(this);
        }

        this.updateRecordArraysLater();
      },

      _unhandledEvent: function(state, name, context) {
        var errorMessage = "Attempted to handle event `" + name + "` ";
        errorMessage    += "on " + String(this) + " while in state ";
        errorMessage    += state.stateName + ". ";

        if (context !== undefined) {
          errorMessage  += "Called with " + Ember.inspect(context) + ".";
        }

        throw new Ember.Error(errorMessage);
      },

      withTransaction: function(fn) {
        var transaction = get(this, 'transaction');
        if (transaction) { fn(transaction); }
      },

      /**
        @method loadingData
        @private
        @param {Promise} promise
      */
      loadingData: function(promise) {
        this.send('loadingData', promise);
      },

      /**
        @method loadedData
        @private
      */
      loadedData: function() {
        this.send('loadedData');
      },

      /**
        @method notFound
        @private
      */
      notFound: function() {
        this.send('notFound');
      },

      /**
        @method pushedData
        @private
      */
      pushedData: function() {
        this.send('pushedData');
      },

      /**
        Marks the record as deleted but does not save it. You must call
        `save` afterwards if you want to persist it. You might use this
        method if you want to allow the user to still `rollback()` a
        delete after it was made.

        Example

        ```javascript
        App.ModelDeleteRoute = Ember.Route.extend({
          actions: {
            softDelete: function() {
              this.get('model').deleteRecord();
            },
            confirm: function() {
              this.get('model').save();
            },
            undo: function() {
              this.get('model').rollback();
            }
          }
        });
        ```

        @method deleteRecord
      */
      deleteRecord: function() {
        this.send('deleteRecord');
      },

      /**
        Same as `deleteRecord`, but saves the record immediately.

        Example

        ```javascript
        App.ModelDeleteRoute = Ember.Route.extend({
          actions: {
            delete: function() {
              var controller = this.controller;
              this.get('model').destroyRecord().then(function() {
                controller.transitionToRoute('model.index');
              });
            }
          }
        });
        ```

        @method destroyRecord
        @return {Promise} a promise that will be resolved when the adapter returns
        successfully or rejected if the adapter returns with an error.
      */
      destroyRecord: function() {
        this.deleteRecord();
        return this.save();
      },

      /**
        @method unloadRecord
        @private
      */
      unloadRecord: function() {
        if (this.isDestroyed) { return; }

        this.send('unloadRecord');
      },

      /**
        @method clearRelationships
        @private
      */
      clearRelationships: function() {
        this.eachRelationship(function(name, relationship) {
          if (relationship.kind === 'belongsTo') {
            set(this, name, null);
          } else if (relationship.kind === 'hasMany') {
            var hasMany = this._relationships[name];
            if (hasMany) { // relationships are created lazily
              hasMany.destroy();
            }
          }
        }, this);
      },

      /**
        @method updateRecordArrays
        @private
      */
      updateRecordArrays: function() {
        this._updatingRecordArraysLater = false;
        get(this, 'store').dataWasUpdated(this.constructor, this);
      },

      /**
        Returns an object, whose keys are changed properties, and value is
        an [oldProp, newProp] array.

        Example

        ```javascript
        App.Mascot = DS.Model.extend({
          name: attr('string')
        });

        var person = store.createRecord('person');
        person.changedAttributes(); // {}
        person.set('name', 'Tomster');
        person.changedAttributes(); // {name: [undefined, 'Tomster']}
        ```

        @method changedAttributes
        @return {Object} an object, whose keys are changed properties,
          and value is an [oldProp, newProp] array.
      */
      changedAttributes: function() {
        var oldData = get(this, '_data'),
            newData = get(this, '_attributes'),
            diffData = {},
            prop;

        for (prop in newData) {
          diffData[prop] = [oldData[prop], newData[prop]];
        }

        return diffData;
      },

      /**
        @method adapterWillCommit
        @private
      */
      adapterWillCommit: function() {
        this.send('willCommit');
      },

      /**
        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
      */
      adapterDidCommit: 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');
        });
      },

      /**
        @method adapterDidDirty
        @private
      */
      adapterDidDirty: function() {
        this.send('becomeDirty');
        this.updateRecordArraysLater();
      },

      dataDidChange: Ember.observer(function() {
        this.reloadHasManys();
      }, 'data'),

      reloadHasManys: function() {
        var relationships = get(this.constructor, 'relationshipsByName');
        this.updateRecordArraysLater();
        relationships.forEach(function(name, relationship) {
          if (this._data.links && this._data.links[name]) { return; }
          if (relationship.kind === 'hasMany') {
            this.hasManyDidChange(relationship.key);
          }
        }, this);
      },

      hasManyDidChange: function(key) {
        var hasMany = this._relationships[key];

        if (hasMany) {
          var records = this._data[key] || [];

          set(hasMany, 'content', Ember.A(records));
          set(hasMany, 'isLoaded', true);
          hasMany.trigger('didLoad');
        }
      },

      /**
        @method updateRecordArraysLater
        @private
      */
      updateRecordArraysLater: function() {
        // quick hack (something like this could be pushed into run.once
        if (this._updatingRecordArraysLater) { return; }
        this._updatingRecordArraysLater = true;

        Ember.run.schedule('actions', this, this.updateRecordArrays);
      },

      /**
        @method setupData
        @private
        @param {Object} data
        @param {Boolean} partial the data should be merged into
          the existing data, not replace it.
      */
      setupData: function(data, partial) {
        if (partial) {
          Ember.merge(this._data, data);
        } else {
          this._data = data;
        }

        var relationships = this._relationships;

        this.eachRelationship(function(name, rel) {
          if (data.links && data.links[name]) { return; }
          if (rel.options.async) { relationships[name] = null; }
        });

        if (data) { this.pushedData(); }

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

      materializeId: function(id) {
        set(this, 'id', id);
      },

      materializeAttributes: function(attributes) {
        Ember.assert("Must pass a hash of attributes to materializeAttributes", !!attributes);
        merge(this._data, attributes);
      },

      materializeAttribute: function(name, value) {
        this._data[name] = value;
      },

      /**
        @method updateHasMany
        @private
        @param {String} name
        @param {Array} records
      */
      updateHasMany: function(name, records) {
        this._data[name] = records;
        this.hasManyDidChange(name);
      },

      /**
        @method updateBelongsTo
        @private
        @param {String} name
        @param {DS.Model} record
      */
      updateBelongsTo: function(name, record) {
        this._data[name] = record;
      },

      /**
        If the model `isDirty` this function will 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
      */
      rollback: 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');
        });
      },

      toStringExtension: function() {
        return get(this, 'id');
      },

      /**
        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
      */
      suspendRelationshipObservers: function(callback, binding) {
        var observers = get(this.constructor, 'relationshipNames').belongsTo;
        var self = this;

        try {
          this._suspendedRelationships = true;
          Ember._suspendObservers(self, observers, null, 'belongsToDidChange', function() {
            Ember._suspendBeforeObservers(self, observers, null, 'belongsToWillChange', function() {
              callback.call(binding || self);
            });
          });
        } finally {
          this._suspendedRelationships = false;
        }
      },

      /**
        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: 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 PromiseObject.create({ promise: resolver.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.
      */
      reload: function() {
        set(this, 'isReloading', true);

        var  record = this;

        var promiseLabel = "DS: Model#reload of " + this;
        var promise = new 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 PromiseObject.create({ promise: promise });
      },

      // FOR USE DURING COMMIT PROCESS

      adapterDidUpdateAttribute: function(attributeName, value) {

        // If a value is passed in, update the internal attributes and clear
        // the attribute cache so it picks up the new value. Otherwise,
        // collapse the current value into the internal attributes because
        // the adapter has acknowledged it.
        if (value !== undefined) {
          this._data[attributeName] = value;
          this.notifyPropertyChange(attributeName);
        } else {
          this._data[attributeName] = this._inFlightAttributes[attributeName];
        }

        this.updateRecordArraysLater();
      },

      /**
        @method adapterDidInvalidate
        @private
      */
      adapterDidInvalidate: function(errors) {
        var recordErrors = get(this, 'errors');
        function addError(name) {
          if (errors[name]) {
            recordErrors.add(name, errors[name]);
          }
        }

        this.eachAttribute(addError);
        this.eachRelationship(addError);
      },

      /**
        @method adapterDidError
        @private
      */
      adapterDidError: function() {
        this.send('becameError');
        set(this, 'isError', true);
      },

      /**
        Override the default event firing from Ember.Evented to
        also call methods with the given name.

        @method trigger
        @private
        @param name
      */
      trigger: function(name) {
        Ember.tryInvoke(this, name, [].slice.call(arguments, 1));
        this._super.apply(this, arguments);
      },

      triggerLater: function() {
        if (this._deferredTriggers.push(arguments) !== 1) { return; }
        Ember.run.schedule('actions', this, '_triggerDeferredTriggers');
      },

      _triggerDeferredTriggers: function() {
        for (var i=0, l=this._deferredTriggers.length; i<l; i++) {
          this.trigger.apply(this, this._deferredTriggers[i]);
        }

        this._deferredTriggers.length = 0;
      },

      willDestroy: function() {
        this._super();
        this.clearRelationships();
      }
    });

    Model.reopenClass({

      /**
        Alias DS.Model's `create` method to `_create`. This allows us to create DS.Model
        instances from within the store, but if end users accidentally call `create()`
        (instead of `createRecord()`), we can raise an error.

        @method _create
        @private
        @static
      */
      _create: Model.create,

      /**
        Override the class' `create()` method to raise an error. This
        prevents end users from inadvertently calling `create()` instead
        of `createRecord()`. The store is still able to create instances
        by calling the `_create()` method. To create an instance of a
        `DS.Model` use [store.createRecord](DS.Store.html#method_createRecord).

        @method create
        @private
        @static
      */
      create: function() {
        throw new Ember.Error("You should not call `create` on a model. Instead, call `store.createRecord` with the attributes you would like to set.");
      }
    });

    __exports__["default"] = Model;
  });
define("ember-data/lib/system/model/states", 
  ["exports"],
  function(__exports__) {
    "use strict";
    /**
      @module ember-data
    */

    var get = Ember.get, set = Ember.set;
    /*
      This file encapsulates the various states that a record can transition
      through during its lifecycle.
    */
    /**
      ### State

      Each record has a `currentState` property that explicitly tracks what
      state a record is in at any given time. For instance, if a record is
      newly created and has not yet been sent to the adapter to be saved,
      it would be in the `root.loaded.created.uncommitted` state.  If a
      record has had local modifications made to it that are in the
      process of being saved, the record would be in the
      `root.loaded.updated.inFlight` state. (These state paths will be
      explained in more detail below.)

      Events are sent by the record or its store to the record's
      `currentState` property. How the state reacts to these events is
      dependent on which state it is in. In some states, certain events
      will be invalid and will cause an exception to be raised.

      States are hierarchical and every state is a substate of the
      `RootState`. For example, a record can be in the
      `root.deleted.uncommitted` state, then transition into the
      `root.deleted.inFlight` state. If a child state does not implement
      an event handler, the state manager will attempt to invoke the event
      on all parent states until the root state is reached. The state
      hierarchy of a record is described in terms of a path string. You
      can determine a record's current state by getting the state's
      `stateName` property:

      ```javascript
      record.get('currentState.stateName');
      //=> "root.created.uncommitted"
       ```

      The hierarchy of valid states that ship with ember data looks like
      this:

      ```text
      * root
        * deleted
          * saved
          * uncommitted
          * inFlight
        * empty
        * loaded
          * created
            * uncommitted
            * inFlight
          * saved
          * updated
            * uncommitted
            * inFlight
        * loading
      ```

      The `DS.Model` states are themselves stateless. What we mean is
      that, the hierarchical states that each of *those* points to is a
      shared data structure. For performance reasons, instead of each
      record getting its own copy of the hierarchy of states, each record
      points to this global, immutable shared instance. How does a state
      know which record it should be acting on? We pass the record
      instance into the state's event handlers as the first argument.

      The record passed as the first parameter is where you should stash
      state about the record if needed; you should never store data on the state
      object itself.

      ### Events and Flags

      A state may implement zero or more events and flags.

      #### Events

      Events are named functions that are invoked when sent to a record. The
      record will first look for a method with the given name on the
      current state. If no method is found, it will search the current
      state's parent, and then its grandparent, and so on until reaching
      the top of the hierarchy. If the root is reached without an event
      handler being found, an exception will be raised. This can be very
      helpful when debugging new features.

      Here's an example implementation of a state with a `myEvent` event handler:

      ```javascript
      aState: DS.State.create({
        myEvent: function(manager, param) {
          console.log("Received myEvent with", param);
        }
      })
      ```

      To trigger this event:

      ```javascript
      record.send('myEvent', 'foo');
      //=> "Received myEvent with foo"
      ```

      Note that an optional parameter can be sent to a record's `send()` method,
      which will be passed as the second parameter to the event handler.

      Events should transition to a different state if appropriate. This can be
      done by calling the record's `transitionTo()` method with a path to the
      desired state. The state manager will attempt to resolve the state path
      relative to the current state. If no state is found at that path, it will
      attempt to resolve it relative to the current state's parent, and then its
      parent, and so on until the root is reached. For example, imagine a hierarchy
      like this:

          * created
            * uncommitted <-- currentState
            * inFlight
          * updated
            * inFlight

      If we are currently in the `uncommitted` state, calling
      `transitionTo('inFlight')` would transition to the `created.inFlight` state,
      while calling `transitionTo('updated.inFlight')` would transition to
      the `updated.inFlight` state.

      Remember that *only events* should ever cause a state transition. You should
      never call `transitionTo()` from outside a state's event handler. If you are
      tempted to do so, create a new event and send that to the state manager.

      #### Flags

      Flags are Boolean values that can be used to introspect a record's current
      state in a more user-friendly way than examining its state path. For example,
      instead of doing this:

      ```javascript
      var statePath = record.get('stateManager.currentPath');
      if (statePath === 'created.inFlight') {
        doSomething();
      }
      ```

      You can say:

      ```javascript
      if (record.get('isNew') && record.get('isSaving')) {
        doSomething();
      }
      ```

      If your state does not set a value for a given flag, the value will
      be inherited from its parent (or the first place in the state hierarchy
      where it is defined).

      The current set of flags are defined below. If you want to add a new flag,
      in addition to the area below, you will also need to declare it in the
      `DS.Model` class.


       * [isEmpty](DS.Model.html#property_isEmpty)
       * [isLoading](DS.Model.html#property_isLoading)
       * [isLoaded](DS.Model.html#property_isLoaded)
       * [isDirty](DS.Model.html#property_isDirty)
       * [isSaving](DS.Model.html#property_isSaving)
       * [isDeleted](DS.Model.html#property_isDeleted)
       * [isNew](DS.Model.html#property_isNew)
       * [isValid](DS.Model.html#property_isValid)

      @namespace DS
      @class RootState
    */

    function hasDefinedProperties(object) {
      // Ignore internal property defined by simulated `Ember.create`.
      var names = Ember.keys(object);
      var i, l, name;
      for (i = 0, l = names.length; i < l; i++ ) {
        name = names[i];
        if (object.hasOwnProperty(name) && object[name]) { return true; }
      }

      return false;
    }

    function didSetProperty(record, context) {
      if (context.value === context.originalValue) {
        delete record._attributes[context.name];
        record.send('propertyWasReset', context.name);
      } else if (context.value !== context.oldValue) {
        record.send('becomeDirty');
      }

      record.updateRecordArraysLater();
    }

    // Implementation notes:
    //
    // Each state has a boolean value for all of the following flags:
    //
    // * isLoaded: The record has a populated `data` property. When a
    //   record is loaded via `store.find`, `isLoaded` is false
    //   until the adapter sets it. When a record is created locally,
    //   its `isLoaded` property is always true.
    // * isDirty: The record has local changes that have not yet been
    //   saved by the adapter. This includes records that have been
    //   created (but not yet saved) or deleted.
    // * isSaving: The record has been committed, but
    //   the adapter has not yet acknowledged that the changes have
    //   been persisted to the backend.
    // * isDeleted: The record was marked for deletion. When `isDeleted`
    //   is true and `isDirty` is true, the record is deleted locally
    //   but the deletion was not yet persisted. When `isSaving` is
    //   true, the change is in-flight. When both `isDirty` and
    //   `isSaving` are false, the change has persisted.
    // * isError: The adapter reported that it was unable to save
    //   local changes to the backend. This may also result in the
    //   record having its `isValid` property become false if the
    //   adapter reported that server-side validations failed.
    // * isNew: The record was created on the client and the adapter
    //   did not yet report that it was successfully saved.
    // * isValid: The adapter did not report any server-side validation
    //   failures.

    // The dirty state is a abstract state whose functionality is
    // shared between the `created` and `updated` states.
    //
    // The deleted state shares the `isDirty` flag with the
    // subclasses of `DirtyState`, but with a very different
    // implementation.
    //
    // Dirty states have three child states:
    //
    // `uncommitted`: the store has not yet handed off the record
    //   to be saved.
    // `inFlight`: the store has handed off the record to be saved,
    //   but the adapter has not yet acknowledged success.
    // `invalid`: the record has invalid information and cannot be
    //   send to the adapter yet.
    var DirtyState = {
      initialState: 'uncommitted',

      // FLAGS
      isDirty: true,

      // SUBSTATES

      // When a record first becomes dirty, it is `uncommitted`.
      // This means that there are local pending changes, but they
      // have not yet begun to be saved, and are not invalid.
      uncommitted: {
        // EVENTS
        didSetProperty: didSetProperty,

        propertyWasReset: function(record, name) {
          var stillDirty = false;

          for (var prop in record._attributes) {
            stillDirty = true;
            break;
          }

          if (!stillDirty) { record.send('rolledBack'); }
        },

        pushedData: Ember.K,

        becomeDirty: Ember.K,

        willCommit: function(record) {
          record.transitionTo('inFlight');
        },

        reloadRecord: function(record, resolve) {
          resolve(get(record, 'store').reloadRecord(record));
        },

        rolledBack: function(record) {
          record.transitionTo('loaded.saved');
        },

        becameInvalid: function(record) {
          record.transitionTo('invalid');
        },

        rollback: function(record) {
          record.rollback();
        }
      },

      // Once a record has been handed off to the adapter to be
      // saved, it is in the 'in flight' state. Changes to the
      // record cannot be made during this window.
      inFlight: {
        // FLAGS
        isSaving: true,

        // EVENTS
        didSetProperty: didSetProperty,
        becomeDirty: Ember.K,
        pushedData: Ember.K,

        unloadRecord: function(record) {
          Ember.assert("You can only unload a record which is not inFlight. `" + Ember.inspect(record) + " `", false);
        },

        // TODO: More robust semantics around save-while-in-flight
        willCommit: Ember.K,

        didCommit: function(record) {
          var dirtyType = get(this, 'dirtyType');

          record.transitionTo('saved');
          record.send('invokeLifecycleCallbacks', dirtyType);
        },

        becameInvalid: function(record) {
          record.transitionTo('invalid');
          record.send('invokeLifecycleCallbacks');
        },

        becameError: function(record) {
          record.transitionTo('uncommitted');
          record.triggerLater('becameError', record);
        }
      },

      // A record is in the `invalid` if the adapter has indicated
      // the the record failed server-side invalidations.
      invalid: {
        // FLAGS
        isValid: false,

        // EVENTS
        deleteRecord: function(record) {
          record.transitionTo('deleted.uncommitted');
          record.clearRelationships();
        },

        didSetProperty: function(record, context) {
          get(record, 'errors').remove(context.name);

          didSetProperty(record, context);
        },

        becomeDirty: Ember.K,

        willCommit: function(record) {
          get(record, 'errors').clear();
          record.transitionTo('inFlight');
        },

        rolledBack: function(record) {
          get(record, 'errors').clear();
        },

        becameValid: function(record) {
          record.transitionTo('uncommitted');
        },

        invokeLifecycleCallbacks: function(record) {
          record.triggerLater('becameInvalid', record);
        },

        exit: function(record) {
          record._inFlightAttributes = {};
        }
      }
    };

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

    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 mixin(original, hash) {
      for (var prop in hash) {
        original[prop] = hash[prop];
      }

      return original;
    }

    function dirtyState(options) {
      var newState = deepClone(DirtyState);
      return mixin(newState, options);
    }

    var createdState = dirtyState({
      dirtyType: 'created',
      // FLAGS
      isNew: true
    });

    createdState.uncommitted.rolledBack = function(record) {
      record.transitionTo('deleted.saved');
    };

    var updatedState = dirtyState({
      dirtyType: 'updated'
    });

    createdState.uncommitted.deleteRecord = function(record) {
      record.clearRelationships();
      record.transitionTo('deleted.saved');
    };

    createdState.uncommitted.rollback = function(record) {
      DirtyState.uncommitted.rollback.apply(this, arguments);
      record.transitionTo('deleted.saved');
    };

    createdState.uncommitted.propertyWasReset = Ember.K;

    function assertAgainstUnloadRecord(record) {
      Ember.assert("You can only unload a record which is not inFlight. `" + Ember.inspect(record) + "`", false);
    }

    updatedState.inFlight.unloadRecord = assertAgainstUnloadRecord;

    updatedState.uncommitted.deleteRecord = function(record) {
      record.transitionTo('deleted.uncommitted');
      record.clearRelationships();
    };

    var RootState = {
      // FLAGS
      isEmpty: false,
      isLoading: false,
      isLoaded: false,
      isDirty: false,
      isSaving: false,
      isDeleted: false,
      isNew: false,
      isValid: true,

      // DEFAULT EVENTS

      // Trying to roll back if you're not in the dirty state
      // doesn't change your state. For example, if you're in the
      // in-flight state, rolling back the record doesn't move
      // you out of the in-flight state.
      rolledBack: Ember.K,
      unloadRecord: function(record) {
        // clear relationships before moving to deleted state
        // otherwise it fails
        record.clearRelationships();
        record.transitionTo('deleted.saved');
      },


      propertyWasReset: Ember.K,

      // SUBSTATES

      // A record begins its lifecycle in the `empty` state.
      // If its data will come from the adapter, it will
      // transition into the `loading` state. Otherwise, if
      // the record is being created on the client, it will
      // transition into the `created` state.
      empty: {
        isEmpty: true,

        // EVENTS
        loadingData: function(record, promise) {
          record._loadingPromise = promise;
          record.transitionTo('loading');
        },

        loadedData: function(record) {
          record.transitionTo('loaded.created.uncommitted');

          record.suspendRelationshipObservers(function() {
            record.notifyPropertyChange('data');
          });
        },

        pushedData: function(record) {
          record.transitionTo('loaded.saved');
          record.triggerLater('didLoad');
        }
      },

      // A record enters this state when the store asks
      // the adapter for its data. It remains in this state
      // until the adapter provides the requested data.
      //
      // Usually, this process is asynchronous, using an
      // XHR to retrieve the data.
      loading: {
        // FLAGS
        isLoading: true,

        exit: function(record) {
          record._loadingPromise = null;
        },

        // EVENTS
        pushedData: function(record) {
          record.transitionTo('loaded.saved');
          record.triggerLater('didLoad');
          set(record, 'isError', false);
        },

        becameError: function(record) {
          record.triggerLater('becameError', record);
        },

        notFound: function(record) {
          record.transitionTo('empty');
        }
      },

      // A record enters this state when its data is populated.
      // Most of a record's lifecycle is spent inside substates
      // of the `loaded` state.
      loaded: {
        initialState: 'saved',

        // FLAGS
        isLoaded: true,

        // SUBSTATES

        // If there are no local changes to a record, it remains
        // in the `saved` state.
        saved: {
          setup: function(record) {
            var attrs = record._attributes,
                isDirty = false;

            for (var prop in attrs) {
              if (attrs.hasOwnProperty(prop)) {
                isDirty = true;
                break;
              }
            }

            if (isDirty) {
              record.adapterDidDirty();
            }
          },

          // EVENTS
          didSetProperty: didSetProperty,

          pushedData: Ember.K,

          becomeDirty: function(record) {
            record.transitionTo('updated.uncommitted');
          },

          willCommit: function(record) {
            record.transitionTo('updated.inFlight');
          },

          reloadRecord: function(record, resolve) {
            resolve(get(record, 'store').reloadRecord(record));
          },

          deleteRecord: function(record) {
            record.transitionTo('deleted.uncommitted');
            record.clearRelationships();
          },

          unloadRecord: function(record) {
            // clear relationships before moving to deleted state
            // otherwise it fails
            record.clearRelationships();
            record.transitionTo('deleted.saved');
          },

          didCommit: function(record) {
            record.send('invokeLifecycleCallbacks', get(record, 'lastDirtyType'));
          },

          // loaded.saved.notFound would be triggered by a failed
          // `reload()` on an unchanged record
          notFound: Ember.K

        },

        // A record is in this state after it has been locally
        // created but before the adapter has indicated that
        // it has been saved.
        created: createdState,

        // A record is in this state if it has already been
        // saved to the server, but there are new local changes
        // that have not yet been saved.
        updated: updatedState
      },

      // A record is in this state if it was deleted from the store.
      deleted: {
        initialState: 'uncommitted',
        dirtyType: 'deleted',

        // FLAGS
        isDeleted: true,
        isLoaded: true,
        isDirty: true,

        // TRANSITIONS
        setup: function(record) {
          record.updateRecordArrays();
        },

        // SUBSTATES

        // When a record is deleted, it enters the `start`
        // state. It will exit this state when the record
        // starts to commit.
        uncommitted: {

          // EVENTS

          willCommit: function(record) {
            record.transitionTo('inFlight');
          },

          rollback: function(record) {
            record.rollback();
          },

          becomeDirty: Ember.K,
          deleteRecord: Ember.K,

          rolledBack: function(record) {
            record.transitionTo('loaded.saved');
          }
        },

        // After a record starts committing, but
        // before the adapter indicates that the deletion
        // has saved to the server, a record is in the
        // `inFlight` substate of `deleted`.
        inFlight: {
          // FLAGS
          isSaving: true,

          // EVENTS

          unloadRecord: assertAgainstUnloadRecord,

          // TODO: More robust semantics around save-while-in-flight
          willCommit: Ember.K,
          didCommit: function(record) {
            record.transitionTo('saved');

            record.send('invokeLifecycleCallbacks');
          },

          becameError: function(record) {
            record.transitionTo('uncommitted');
            record.triggerLater('becameError', record);
          }
        },

        // Once the adapter indicates that the deletion has
        // been saved, the record enters the `saved` substate
        // of `deleted`.
        saved: {
          // FLAGS
          isDirty: false,

          setup: function(record) {
            var store = get(record, 'store');
            store.dematerializeRecord(record);
          },

          invokeLifecycleCallbacks: function(record) {
            record.triggerLater('didDelete', record);
            record.triggerLater('didCommit', record);
          },

          willCommit: Ember.K,

          didCommit: Ember.K
        }
      },

      invokeLifecycleCallbacks: function(record, dirtyType) {
        if (dirtyType === 'created') {
          record.triggerLater('didCreate', record);
        } else {
          record.triggerLater('didUpdate', record);
        }

        record.triggerLater('didCommit', record);
      }
    };

    function wireState(object, parent, name) {
      /*jshint proto:true*/
      // TODO: Use Object.create and copy instead
      object = mixin(parent ? Ember.create(parent) : {}, object);
      object.parentState = parent;
      object.stateName = name;

      for (var prop in object) {
        if (!object.hasOwnProperty(prop) || prop === 'parentState' || prop === 'stateName') { continue; }
        if (typeof object[prop] === 'object') {
          object[prop] = wireState(object[prop], object, name + "." + prop);
        }
      }

      return object;
    }

    RootState = wireState(RootState, null, "root");

    __exports__["default"] = RootState;
  });
define("ember-data/lib/system/record_array_manager", 
  ["./record_arrays","exports"],
  function(__dependency1__, __exports__) {
    "use strict";
    /**
      @module ember-data
    */

    var RecordArray = __dependency1__.RecordArray;
    var FilteredRecordArray = __dependency1__.FilteredRecordArray;
    var AdapterPopulatedRecordArray = __dependency1__.AdapterPopulatedRecordArray;
    var ManyArray = __dependency1__.ManyArray;
    var get = Ember.get, set = Ember.set;
    var forEach = Ember.EnumerableUtils.forEach;

    /**
      @class RecordArrayManager
      @namespace DS
      @private
      @extends Ember.Object
    */
    var RecordArrayManager = Ember.Object.extend({
      init: function() {
        this.filteredRecordArrays = Ember.MapWithDefault.create({
          defaultValue: function() { return []; }
        });

        this.changedRecords = [];
        this._adapterPopulatedRecordArrays = [];
      },

      recordDidChange: function(record) {
        if (this.changedRecords.push(record) !== 1) { return; }

        Ember.run.schedule('actions', this, this.updateRecordArrays);
      },

      recordArraysForRecord: function(record) {
        record._recordArrays = record._recordArrays || Ember.OrderedSet.create();
        return record._recordArrays;
      },

      /**
        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
      */
      updateRecordArrays: function() {
        forEach(this.changedRecords, function(record) {
          if (get(record, 'isDeleted')) {
            this._recordWasDeleted(record);
          } else {
            this._recordWasChanged(record);
          }
        }, this);

        this.changedRecords.length = 0;
      },

      _recordWasDeleted: function (record) {
        var recordArrays = record._recordArrays;

        if (!recordArrays) { return; }

        forEach(recordArrays, function(array) {
          array.removeRecord(record);
        });
      },

      _recordWasChanged: function (record) {
        var type = record.constructor,
            recordArrays = this.filteredRecordArrays.get(type),
            filter;

        forEach(recordArrays, function(array) {
          filter = get(array, 'filterFunction');
          this.updateRecordArray(array, filter, type, record);
        }, this);

        // loop through all manyArrays containing an unloaded copy of this
        // clientId and notify them that the record was loaded.
        var manyArrays = record._loadingRecordArrays;

        if (manyArrays) {
          for (var i=0, l=manyArrays.length; i<l; i++) {
            manyArrays[i].loadedRecord();
          }

          record._loadingRecordArrays = [];
        }
      },

      /**
        Update an individual filter.

        @method updateRecordArray
        @param {DS.FilteredRecordArray} array
        @param {Function} filter
        @param {Class} type
        @param {Number|String} clientId
      */
      updateRecordArray: 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);
        }
      },

      /**
        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
      */
      updateFilter: 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);
          }
        }
      },

      /**
        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}
      */
      createManyArray: function(type, records) {
        var manyArray = 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.RecordArray` for a type and register it for updates.

        @method createRecordArray
        @param {Class} type
        @return {DS.RecordArray}
      */
      createRecordArray: function(type) {
        var array = RecordArray.create({
          type: type,
          content: Ember.A(),
          store: this.store,
          isLoaded: true
        });

        this.registerFilteredRecordArray(array, type);

        return array;
      },

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

        @method createFilteredRecordArray
        @param {Class} type
        @param {Function} filter
        @param {Object} query (optional
        @return {DS.FilteredRecordArray}
      */
      createFilteredRecordArray: function(type, filter, query) {
        var array = FilteredRecordArray.create({
          query: query,
          type: type,
          content: Ember.A(),
          store: this.store,
          manager: this,
          filterFunction: filter
        });

        this.registerFilteredRecordArray(array, type, filter);

        return array;
      },

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

        @method createAdapterPopulatedRecordArray
        @param {Class} type
        @param {Object} query
        @return {DS.AdapterPopulatedRecordArray}
      */
      createAdapterPopulatedRecordArray: function(type, query) {
        var array = AdapterPopulatedRecordArray.create({
          type: type,
          query: query,
          content: Ember.A(),
          store: this.store,
          manager: this
        });

        this._adapterPopulatedRecordArrays.push(array);

        return array;
      },

      /**
        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
      */
      registerFilteredRecordArray: function(array, type, filter) {
        var recordArrays = this.filteredRecordArrays.get(type);
        recordArrays.push(array);

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

      // 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.
      registerWaitingRecordArray: function(record, array) {
        var loadingRecordArrays = record._loadingRecordArrays || [];
        loadingRecordArrays.push(array);
        record._loadingRecordArrays = loadingRecordArrays;
      },

      willDestroy: function(){
        this._super();

        forEach(flatten(values(this.filteredRecordArrays.values)), destroy);
        forEach(this._adapterPopulatedRecordArrays, destroy);
      }
    });

    function values(obj) {
      var result = [];
      var keys = Ember.keys(obj);

      for (var i = 0; i < keys.length; i++) {
        result.push(obj[keys[i]]);
      }

      return result;
    }

    function destroy(entry) {
      entry.destroy();
    }

    function flatten(list) {
      var length = list.length;
      var result = Ember.A();

      for (var i = 0; i < length; i++) {
        result = result.concat(list[i]);
      }

      return result;
    }

    __exports__["default"] = RecordArrayManager;
  });
define("ember-data/lib/system/record_arrays", 
  ["./record_arrays/record_array","./record_arrays/filtered_record_array","./record_arrays/adapter_populated_record_array","./record_arrays/many_array","exports"],
  function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
    "use strict";
    /**
      @module ember-data
    */

    var RecordArray = __dependency1__["default"];
    var FilteredRecordArray = __dependency2__["default"];
    var AdapterPopulatedRecordArray = __dependency3__["default"];
    var ManyArray = __dependency4__["default"];

    __exports__.RecordArray = RecordArray;
    __exports__.FilteredRecordArray = FilteredRecordArray;
    __exports__.AdapterPopulatedRecordArray = AdapterPopulatedRecordArray;
    __exports__.ManyArray = ManyArray;
  });
define("ember-data/lib/system/record_arrays/adapter_populated_record_array", 
  ["./record_array","exports"],
  function(__dependency1__, __exports__) {
    "use strict";
    var RecordArray = __dependency1__["default"];
    /**
      @module ember-data
    */

    var get = Ember.get, set = Ember.set;

    /**
      Represents an ordered list of records whose order and membership is
      determined by the adapter. For example, a query sent to the adapter
      may trigger a search on the server, whose results would be loaded
      into an instance of the `AdapterPopulatedRecordArray`.

      @class AdapterPopulatedRecordArray
      @namespace DS
      @extends DS.RecordArray
    */
    var AdapterPopulatedRecordArray = RecordArray.extend({
      query: null,

      replace: function() {
        var type = get(this, 'type').toString();
        throw new Error("The result of a server query (on " + type + ") is immutable.");
      },

      /**
        @method load
        @private
        @param {Array} data
      */
      load: function(data) {
        var store = get(this, 'store'),
            type = get(this, 'type'),
            records = store.pushMany(type, data),
            meta = store.metadataFor(type);

        this.setProperties({
          content: Ember.A(records),
          isLoaded: true,
          meta: Ember.copy(meta)
        });

        records.forEach(function(record) {
          this.manager.recordArraysForRecord(record).add(this);
        }, this);

        // TODO: should triggering didLoad event be the last action of the runLoop?
        Ember.run.once(this, 'trigger', 'didLoad');
      }
    });

    __exports__["default"] = AdapterPopulatedRecordArray;
  });
define("ember-data/lib/system/record_arrays/filtered_record_array", 
  ["./record_array","exports"],
  function(__dependency1__, __exports__) {
    "use strict";
    var RecordArray = __dependency1__["default"];

    /**
      @module ember-data
    */

    var get = Ember.get;

    /**
      Represents a list of records whose membership is determined by the
      store. As records are created, loaded, or modified, the store
      evaluates them to determine if they should be part of the record
      array.

      @class FilteredRecordArray
      @namespace DS
      @extends DS.RecordArray
    */
    var FilteredRecordArray = RecordArray.extend({
      /**
        The filterFunction is a function used to test records from the store to
        determine if they should be part of the record array.

        Example

        ```javascript
        var allPeople = store.all('person');
        allPeople.mapBy('name'); // ["Tom Dale", "Yehuda Katz", "Trek Glowacki"]

        var people = store.filter('person', function(person) {
          if (person.get('name').match(/Katz$/)) { return true; }
        });
        people.mapBy('name'); // ["Yehuda Katz"]

        var notKatzFilter = function(person) {
          return !person.get('name').match(/Katz$/);
        };
        people.set('filterFunction', notKatzFilter);
        people.mapBy('name'); // ["Tom Dale", "Trek Glowacki"]
        ```

        @method filterFunction
        @param {DS.Model} record
        @return {Boolean} `true` if the record should be in the array
      */
      filterFunction: null,
      isLoaded: true,

      replace: function() {
        var type = get(this, 'type').toString();
        throw new Error("The result of a client-side filter (on " + type + ") is immutable.");
      },

      /**
        @method updateFilter
        @private
      */
      _updateFilter: function() {
        var manager = get(this, 'manager');
        manager.updateFilter(this, get(this, 'type'), get(this, 'filterFunction'));
      },

      updateFilter: Ember.observer(function() {
        Ember.run.once(this, this._updateFilter);
      }, 'filterFunction')
    });

    __exports__["default"] = FilteredRecordArray;
  });
define("ember-data/lib/system/record_arrays/many_array", 
  ["./record_array","../changes","exports"],
  function(__dependency1__, __dependency2__, __exports__) {
    "use strict";
    var RecordArray = __dependency1__["default"];
    var RelationshipChange = __dependency2__.RelationshipChange;

    /**
      @module ember-data
    */

    var get = Ember.get, set = Ember.set;
    var map = Ember.EnumerableUtils.map;

    function sync(change) {
      change.sync();
    }

    /**
      A `ManyArray` is a `RecordArray` that represents the contents of a has-many
      relationship.

      The `ManyArray` is instantiated lazily the first time the relationship is
      requested.

      ### Inverses

      Often, the relationships in Ember Data applications will have
      an inverse. For example, imagine the following models are
      defined:

      ```javascript
      App.Post = DS.Model.extend({
        comments: DS.hasMany('comment')
      });

      App.Comment = DS.Model.extend({
        post: DS.belongsTo('post')
      });
      ```

      If you created a new instance of `App.Post` and added
      a `App.Comment` record to its `comments` has-many
      relationship, you would expect the comment's `post`
      property to be set to the post that contained
      the has-many.

      We call the record to which a relationship belongs the
      relationship's _owner_.

      @class ManyArray
      @namespace DS
      @extends DS.RecordArray
    */
    var ManyArray = RecordArray.extend({
      init: function() {
        this._super.apply(this, arguments);
        this._changesToSync = Ember.OrderedSet.create();
      },

      /**
        The property name of the relationship

        @property {String} name
        @private
      */
      name: null,

      /**
        The record to which this relationship belongs.

        @property {DS.Model} owner
        @private
      */
      owner: null,

      /**
        `true` if the relationship is polymorphic, `false` otherwise.

        @property {Boolean} isPolymorphic
        @private
      */
      isPolymorphic: false,

      // LOADING STATE

      isLoaded: false,

      /**
        Used for async `hasMany` arrays
        to keep track of when they will resolve.

        @property {Ember.RSVP.Promise} promise
        @private
      */
      promise: null,

      /**
        @method loadingRecordsCount
        @param {Number} count
        @private
      */
      loadingRecordsCount: function(count) {
        this.loadingRecordsCount = count;
      },

      /**
        @method loadedRecord
        @private
      */
      loadedRecord: function() {
        this.loadingRecordsCount--;
        if (this.loadingRecordsCount === 0) {
          set(this, 'isLoaded', true);
          this.trigger('didLoad');
        }
      },

      /**
        @method fetch
        @private
      */
      fetch: function() {
        var records = get(this, 'content'),
            store = get(this, 'store'),
            owner = get(this, 'owner');

        var unloadedRecords = records.filterProperty('isEmpty', true);
        store.fetchMany(unloadedRecords, owner);
      },

      // Overrides Ember.Array's replace method to implement
      replaceContent: function(index, removed, added) {
        // Map the array of record objects into an array of  client ids.
        added = 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);
      },

      arrangedContentDidChange: function() {
        Ember.run.once(this, 'fetch');
      },

      arrayContentWillChange: function(index, removed, added) {
        var owner = get(this, 'owner'),
            name = get(this, 'name');

        if (!owner._suspendedRelationships) {
          // This code is the first half of code that continues inside
          // of arrayContentDidChange. It gets or creates a change from
          // the child object, adds the current owner as the old
          // parent if this is the first time the object was removed
          // from a ManyArray, and sets `newParent` to null.
          //
          // Later, if the object is added to another ManyArray,
          // the `arrayContentDidChange` will set `newParent` on
          // the change.
          for (var i=index; i<index+removed; i++) {
            var record = get(this, 'content').objectAt(i);

            var change = RelationshipChange.createChange(owner, record, get(this, 'store'), {
              parentType: owner.constructor,
              changeType: "remove",
              kind: "hasMany",
              key: name
            });

            this._changesToSync.add(change);
          }
        }

        return this._super.apply(this, arguments);
      },

      arrayContentDidChange: function(index, removed, added) {
        this._super.apply(this, arguments);

        var owner = get(this, 'owner'),
            name = get(this, 'name'),
            store = get(this, 'store');

        if (!owner._suspendedRelationships) {
          // This code is the second half of code that started in
          // `arrayContentWillChange`. It gets or creates a change
          // from the child object, and adds the current owner as
          // the new parent.
          for (var i=index; i<index+added; i++) {
            var record = get(this, 'content').objectAt(i);

            var change = RelationshipChange.createChange(owner, record, store, {
              parentType: owner.constructor,
              changeType: "add",
              kind:"hasMany",
              key: name
            });
            change.hasManyName = name;

            this._changesToSync.add(change);
          }

          // We wait until the array has finished being
          // mutated before syncing the OneToManyChanges created
          // in arrayContentWillChange, so that the array
          // membership test in the sync() logic operates
          // on the final results.
          this._changesToSync.forEach(sync);

          this._changesToSync.clear();
        }
      },

      /**
        Create a child record within the owner

        @method createRecord
        @private
        @param {Object} hash
        @return {DS.Model} record
      */
      createRecord: 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;
      }
    });

    __exports__["default"] = ManyArray;
  });
define("ember-data/lib/system/record_arrays/record_array", 
  ["../store","exports"],
  function(__dependency1__, __exports__) {
    "use strict";
    /**
      @module ember-data
    */

    var PromiseArray = __dependency1__.PromiseArray;
    var get = Ember.get, set = Ember.set;

    /**
      A record array is an array that contains records of a certain type. The record
      array materializes records as needed when they are retrieved for the first
      time. You should not create record arrays yourself. Instead, an instance of
      `DS.RecordArray` or its subclasses will be returned by your application's store
      in response to queries.

      @class RecordArray
      @namespace DS
      @extends Ember.ArrayProxy
      @uses Ember.Evented
    */

    var RecordArray = Ember.ArrayProxy.extend(Ember.Evented, {
      /**
        The model type contained by this record array.

        @property type
        @type DS.Model
      */
      type: null,

      /**
        The array of client ids backing the record array. When a
        record is requested from the record array, the record
        for the client id at the same index is materialized, if
        necessary, by the store.

        @property content
        @private
        @type Ember.Array
      */
      content: null,

      /**
        The flag to signal a `RecordArray` is currently loading data.

        Example

        ```javascript
        var people = store.all('person');
        people.get('isLoaded'); // true
        ```

        @property isLoaded
        @type Boolean
      */
      isLoaded: false,
      /**
        The flag to signal a `RecordArray` is currently loading data.

        Example

        ```javascript
        var people = store.all('person');
        people.get('isUpdating'); // false
        people.update();
        people.get('isUpdating'); // true
        ```

        @property isUpdating
        @type Boolean
      */
      isUpdating: false,

      /**
        The store that created this record array.

        @property store
        @private
        @type DS.Store
      */
      store: null,

      /**
        Retrieves an object from the content by index.

        @method objectAtContent
        @private
        @param {Number} index
        @return {DS.Model} record
      */
      objectAtContent: function(index) {
        var content = get(this, 'content');

        return content.objectAt(index);
      },

      /**
        Used to get the latest version of all of the records in this array
        from the adapter.

        Example

        ```javascript
        var people = store.all('person');
        people.get('isUpdating'); // false
        people.update();
        people.get('isUpdating'); // true
        ```

        @method update
      */
      update: function() {
        if (get(this, 'isUpdating')) { return; }

        var store = get(this, 'store'),
            type = get(this, 'type');

        return store.fetchAll(type, this);
      },

      /**
        Adds a record to the `RecordArray`.

        @method addRecord
        @private
        @param {DS.Model} record
      */
      addRecord: function(record) {
        get(this, 'content').addObject(record);
      },

      /**
        Removes a record to the `RecordArray`.

        @method removeRecord
        @private
        @param {DS.Model} record
      */
      removeRecord: function(record) {
        get(this, 'content').removeObject(record);
      },

      /**
        Saves all of the records in the `RecordArray`.

        Example

        ```javascript
        var messages = store.all('message');
        messages.forEach(function(message) {
          message.set('hasBeenSeen', true);
        });
        messages.save();
        ```

        @method save
        @return {DS.PromiseArray} promise
      */
      save: function() {
        var promiseLabel = "DS: RecordArray#save " + get(this, 'type');
        var promise = Ember.RSVP.all(this.invoke("save"), promiseLabel).then(function(array) {
          return Ember.A(array);
        }, null, "DS: RecordArray#save apply Ember.NativeArray");

        return PromiseArray.create({ promise: promise });
      },

      _dissociateFromOwnRecords: function() {
        var array = this;

        this.forEach(function(record){
          var recordArrays = record._recordArrays;

          if (recordArrays) {
            recordArrays.remove(array);
          }
        });
      },

      willDestroy: function(){
        this._dissociateFromOwnRecords();
        this._super();
      }
    });

    __exports__["default"] = RecordArray;
  });
define("ember-data/lib/system/relationship-meta", 
  ["../../../ember-inflector/lib/system","exports"],
  function(__dependency1__, __exports__) {
    "use strict";
    var singularize = __dependency1__.singularize;

    function typeForRelationshipMeta(store, meta) {
      var typeKey, type;

      typeKey = meta.type || meta.key;
      if (typeof typeKey === 'string') {
        if (meta.kind === 'hasMany') {
          typeKey = singularize(typeKey);
        }
        type = store.modelFor(typeKey);
      } else {
        type = meta.type;
      }

      return type;
    }

    __exports__.typeForRelationshipMeta = typeForRelationshipMeta;function relationshipFromMeta(store, meta) {
      return {
        key:  meta.key,
        kind: meta.kind,
        type: typeForRelationshipMeta(store, meta),
        options:    meta.options,
        parentType: meta.parentType,
        isRelationship: true
      };
    }

    __exports__.relationshipFromMeta = relationshipFromMeta;
  });
define("ember-data/lib/system/relationships", 
  ["./relationships/belongs_to","./relationships/has_many","../system/relationships/ext","exports"],
  function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
    "use strict";
    /**
      @module ember-data
    */

    var belongsTo = __dependency1__["default"];
    var hasMany = __dependency2__["default"];


    __exports__.belongsTo = belongsTo;
    __exports__.hasMany = hasMany;
  });
define("ember-data/lib/system/relationships/belongs_to", 
  ["../model","../store","../changes","../relationship-meta","exports"],
  function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
    "use strict";
    var get = Ember.get, set = Ember.set,
        isNone = Ember.isNone;

    var Promise = Ember.RSVP.Promise;

    var Model = __dependency1__.Model;
    var PromiseObject = __dependency2__.PromiseObject;
    var RelationshipChange = __dependency3__.RelationshipChange;
    var relationshipFromMeta = __dependency4__.relationshipFromMeta;
    var typeForRelationshipMeta = __dependency4__.typeForRelationshipMeta;

    /**
      @module ember-data
    */

    function asyncBelongsTo(type, options, meta) {
      return Ember.computed('data', function(key, value) {
        var data = get(this, 'data'),
            store = get(this, 'store'),
            promiseLabel = "DS: Async belongsTo " + this + " : " + key,
            promise;

        meta.key = key;

        if (arguments.length === 2) {
          Ember.assert("You can only add a '" + type + "' record to this relationship", !value || value instanceof typeForRelationshipMeta(store, meta));
          return value === undefined ? null : PromiseObject.create({
            promise: Promise.cast(value, promiseLabel)
          });
        }

        var link = data.links && data.links[key],
            belongsTo = data[key];

        if(!isNone(belongsTo)) {
          promise = store.fetchRecord(belongsTo) || Promise.cast(belongsTo, promiseLabel);
          return PromiseObject.create({
            promise: promise
          });
        } else if (link) {
          promise = store.findBelongsTo(this, link, relationshipFromMeta(store, meta));
          return PromiseObject.create({
            promise: promise
          });
        } else {
          return null;
        }
      }).meta(meta);
    }

    /**
      `DS.belongsTo` is used to define One-To-One and One-To-Many
      relationships on a [DS.Model](/api/data/classes/DS.Model.html).


      `DS.belongsTo` takes an optional hash as a second parameter, currently
      supported options are:

      - `async`: A boolean value used to explicitly declare this to be an async relationship.
      - `inverse`: A string used to identify the inverse property on a
        related model in a One-To-Many relationship. See [Explicit Inverses](#toc_explicit-inverses)

      #### One-To-One
      To declare a one-to-one relationship between two models, use
      `DS.belongsTo`:

      ```javascript
      App.User = DS.Model.extend({
        profile: DS.belongsTo('profile')
      });

      App.Profile = DS.Model.extend({
        user: DS.belongsTo('user')
      });
      ```

      #### One-To-Many
      To declare a one-to-many relationship between two models, use
      `DS.belongsTo` in combination with `DS.hasMany`, like this:

      ```javascript
      App.Post = DS.Model.extend({
        comments: DS.hasMany('comment')
      });

      App.Comment = DS.Model.extend({
        post: DS.belongsTo('post')
      });
      ```

      @namespace
      @method belongsTo
      @for DS
      @param {String or DS.Model} type the model type of the relationship
      @param {Object} options a hash of options
      @return {Ember.computed} relationship
    */
    function belongsTo(type, options) {
      if (typeof type === 'object') {
        options = type;
        type = undefined;
      } else {
        Ember.assert("The first argument to DS.belongsTo must be a string representing a model type key, e.g. use DS.belongsTo('person') to define a relation to the App.Person model", !!type && (typeof type === 'string' || Model.detect(type)));
      }

      options = options || {};

      var meta = {
        type: type,
        isRelationship: true,
        options: options,
        kind: 'belongsTo',
        key: null
      };

      if (options.async) {
        return asyncBelongsTo(type, options, meta);
      }

      return Ember.computed('data', function(key, value) {
        var data = get(this, 'data'),
            store = get(this, 'store'), belongsTo, typeClass;

        if (typeof type === 'string') {
          typeClass = store.modelFor(type);
        } else {
          typeClass = type;
        }

        if (arguments.length === 2) {
          Ember.assert("You can only add a '" + type + "' record to this relationship", !value || value instanceof typeClass);
          return value === undefined ? null : value;
        }

        belongsTo = data[key];

        if (isNone(belongsTo)) { return null; }

        store.fetchRecord(belongsTo);

        return belongsTo;
      }).meta(meta);
    }

    /**
      These observers observe all `belongsTo` relationships on the record. See
      `relationships/ext` to see how these observers get their dependencies.

      @class Model
      @namespace DS
    */
    Model.reopen({

      /**
        @method belongsToWillChange
        @private
        @static
        @param record
        @param key
      */
      belongsToWillChange: Ember.beforeObserver(function(record, key) {
        if (get(record, 'isLoaded')) {
          var oldParent = get(record, key);

          if (oldParent) {
            var store = get(record, 'store'),
                change = RelationshipChange.createChange(record, oldParent, store, { key: key, kind: "belongsTo", changeType: "remove" });

            change.sync();
            this._changesToSync[key] = change;
          }
        }
      }),

      /**
        @method belongsToDidChange
        @private
        @static
        @param record
        @param key
      */
      belongsToDidChange: Ember.immediateObserver(function(record, key) {
        if (get(record, 'isLoaded')) {
          var newParent = get(record, key);

          if (newParent) {
            var store = get(record, 'store'),
                change = RelationshipChange.createChange(record, newParent, store, { key: key, kind: "belongsTo", changeType: "add" });

            change.sync();
          }
        }

        delete this._changesToSync[key];
      })
    });

    __exports__["default"] = belongsTo;
  });
define("ember-data/lib/system/relationships/ext", 
  ["../../../../ember-inflector/lib/system","../relationship-meta","../model"],
  function(__dependency1__, __dependency2__, __dependency3__) {
    "use strict";
    var singularize = __dependency1__.singularize;
    var typeForRelationshipMeta = __dependency2__.typeForRelationshipMeta;
    var relationshipFromMeta = __dependency2__.relationshipFromMeta;
    var Model = __dependency3__.Model;

    var get = Ember.get, set = Ember.set;

    /**
      @module ember-data
    */

    /*
      This file defines several extensions to the base `DS.Model` class that
      add support for one-to-many relationships.
    */

    /**
      @class Model
      @namespace DS
    */
    Model.reopen({

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

        In this case, we use it to be notified when an Ember Data user defines a
        belongs-to relationship. In that case, we need to set up observers for
        each one, allowing us to track relationship changes and automatically
        reflect changes in the inverse has-many array.

        This hook passes the class being set up, as well as the key and value
        being defined. So, for example, when the user does this:

        ```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
      */
      didDefineProperty: function(proto, key, value) {
        // Check if the value being set is a computed property.
        if (value instanceof Ember.Descriptor) {

          // If it is, get the metadata for the relationship. This is
          // populated by the `DS.belongsTo` helper when it is creating
          // the computed property.
          var meta = value.meta();

          if (meta.isRelationship && meta.kind === 'belongsTo') {
            Ember.addObserver(proto, key, null, 'belongsToDidChange');
            Ember.addBeforeObserver(proto, key, null, 'belongsToWillChange');
          }

          meta.parentType = proto.constructor;
        }
      }
    });

    /*
      These DS.Model extensions add class methods that provide relationship
      introspection abilities about relationships.

      A note about the computed properties contained here:

      **These properties are effectively sealed once called for the first time.**
      To avoid repeatedly doing expensive iteration over a model's fields, these
      values are computed once and then cached for the remainder of the runtime of
      your application.

      If your application needs to modify a class after its initial definition
      (for example, using `reopen()` to add additional attributes), make sure you
      do it before using your model with the store, which uses these properties
      extensively.
    */

    Model.reopenClass({
      /**
        For a given relationship name, returns the model type of the relationship.

        For example, if you define a model like this:

       ```javascript
        App.Post = DS.Model.extend({
          comments: DS.hasMany('comment')
        });
       ```

        Calling `App.Post.typeForRelationship('comments')` will return `App.Comment`.

        @method typeForRelationship
        @static
        @param {String} name the name of the relationship
        @return {subclass of DS.Model} the type of the relationship, or undefined
      */
      typeForRelationship: function(name) {
        var relationship = get(this, 'relationshipsByName').get(name);
        return relationship && relationship.type;
      },

      inverseFor: function(name) {
        var inverseType = this.typeForRelationship(name);

        if (!inverseType) { return null; }

        var options = this.metaForProperty(name).options;

        if (options.inverse === null) { return null; }

        var inverseName, inverseKind;

        if (options.inverse) {
          inverseName = options.inverse;
          inverseKind = Ember.get(inverseType, 'relationshipsByName').get(inverseName).kind;
        } else {
          var possibleRelationships = findPossibleInverses(this, inverseType);

          if (possibleRelationships.length === 0) { return null; }

          Ember.assert("You defined the '" + name + "' relationship on " + this + ", but multiple possible inverse relationships of type " + this + " were found on " + inverseType + ". Look at http://emberjs.com/guides/models/defining-models/#toc_explicit-inverses for how to explicitly specify inverses", possibleRelationships.length === 1);

          inverseName = possibleRelationships[0].name;
          inverseKind = possibleRelationships[0].kind;
        }

        function findPossibleInverses(type, inverseType, possibleRelationships) {
          possibleRelationships = possibleRelationships || [];

          var relationshipMap = get(inverseType, 'relationships');
          if (!relationshipMap) { return; }

          var relationships = relationshipMap.get(type);
          if (relationships) {
            possibleRelationships.push.apply(possibleRelationships, relationshipMap.get(type));
          }

          if (type.superclass) {
            findPossibleInverses(type.superclass, inverseType, possibleRelationships);
          }

          return possibleRelationships;
        }

        return {
          type: inverseType,
          name: inverseName,
          kind: inverseKind
        };
      },

      /**
        The model's relationships as a map, keyed on the type of the
        relationship. The value of each entry is an array containing a descriptor
        for each relationship with that type, describing the name of the relationship
        as well as the type.

        For example, given the following model definition:

        ```javascript
        App.Blog = DS.Model.extend({
          users: DS.hasMany('user'),
          owner: DS.belongsTo('user'),
          posts: DS.hasMany('post')
        });
        ```

        This computed property would return a map describing these
        relationships, like this:

        ```javascript
        var relationships = Ember.get(App.Blog, 'relationships');
        relationships.get(App.User);
        //=> [ { name: 'users', kind: 'hasMany' },
        //     { name: 'owner', kind: 'belongsTo' } ]
        relationships.get(App.Post);
        //=> [ { name: 'posts', kind: 'hasMany' } ]
        ```

        @property relationships
        @static
        @type Ember.Map
        @readOnly
      */
      relationships: Ember.computed(function() {
        var map = new Ember.MapWithDefault({
          defaultValue: function() { return []; }
        });

        // Loop through each computed property on the class
        this.eachComputedProperty(function(name, meta) {

          // If the computed property is a relationship, add
          // it to the map.
          if (meta.isRelationship) {
            meta.key = name;
            var relationshipsForType = map.get(typeForRelationshipMeta(this.store, meta));

            relationshipsForType.push({ name: name, kind: meta.kind });
          }
        });

        return map;
      }).cacheable(false),

      /**
        A hash containing lists of the model's relationships, grouped
        by the relationship kind. For example, given a model with this
        definition:

        ```javascript
        App.Blog = DS.Model.extend({
          users: DS.hasMany('user'),
          owner: DS.belongsTo('user'),

          posts: DS.hasMany('post')
        });
        ```

        This property would contain the following:

        ```javascript
        var relationshipNames = Ember.get(App.Blog, 'relationshipNames');
        relationshipNames.hasMany;
        //=> ['users', 'posts']
        relationshipNames.belongsTo;
        //=> ['owner']
        ```

        @property relationshipNames
        @static
        @type Object
        @readOnly
      */
      relationshipNames: Ember.computed(function() {
        var names = { hasMany: [], belongsTo: [] };

        this.eachComputedProperty(function(name, meta) {
          if (meta.isRelationship) {
            names[meta.kind].push(name);
          }
        });

        return names;
      }),

      /**
        An array of types directly related to a model. Each type will be
        included once, regardless of the number of relationships it has with
        the model.

        For example, given a model with this definition:

        ```javascript
        App.Blog = DS.Model.extend({
          users: DS.hasMany('user'),
          owner: DS.belongsTo('user'),

          posts: DS.hasMany('post')
        });
        ```

        This property would contain the following:

        ```javascript
        var relatedTypes = Ember.get(App.Blog, 'relatedTypes');
        //=> [ App.User, App.Post ]
        ```

        @property relatedTypes
        @static
        @type Ember.Array
        @readOnly
      */
      relatedTypes: Ember.computed(function() {
        var type,
            types = Ember.A();

        // Loop through each computed property on the class,
        // and create an array of the unique types involved
        // in relationships
        this.eachComputedProperty(function(name, meta) {
          if (meta.isRelationship) {
            meta.key = name;
            type = typeForRelationshipMeta(this.store, meta);

            Ember.assert("You specified a hasMany (" + meta.type + ") on " + meta.parentType + " but " + meta.type + " was not found.",  type);

            if (!types.contains(type)) {
              Ember.assert("Trying to sideload " + name + " on " + this.toString() + " but the type doesn't exist.", !!type);
              types.push(type);
            }
          }
        });

        return types;
      }).cacheable(false),

      /**
        A map whose keys are the relationships of a model and whose values are
        relationship descriptors.

        For example, given a model with this
        definition:

        ```javascript
        App.Blog = DS.Model.extend({
          users: DS.hasMany('user'),
          owner: DS.belongsTo('user'),

          posts: DS.hasMany('post')
        });
        ```

        This property would contain the following:

        ```javascript
        var relationshipsByName = Ember.get(App.Blog, 'relationshipsByName');
        relationshipsByName.get('users');
        //=> { key: 'users', kind: 'hasMany', type: App.User }
        relationshipsByName.get('owner');
        //=> { key: 'owner', kind: 'belongsTo', type: App.User }
        ```

        @property relationshipsByName
        @static
        @type Ember.Map
        @readOnly
      */
      relationshipsByName: Ember.computed(function() {
        var map = Ember.Map.create();

        this.eachComputedProperty(function(name, meta) {
          if (meta.isRelationship) {
            meta.key = name;
            var relationship = relationshipFromMeta(this.store, meta);
            relationship.type = typeForRelationshipMeta(this.store, meta);
            map.set(name, relationship);
          }
        });

        return map;
      }).cacheable(false),

      /**
        A map whose keys are the fields of the model and whose values are strings
        describing the kind of the field. A model's fields are the union of all of its
        attributes and relationships.

        For example:

        ```javascript

        App.Blog = DS.Model.extend({
          users: DS.hasMany('user'),
          owner: DS.belongsTo('user'),

          posts: DS.hasMany('post'),

          title: DS.attr('string')
        });

        var fields = Ember.get(App.Blog, 'fields');
        fields.forEach(function(field, kind) {
          console.log(field, kind);
        });

        // prints:
        // users, hasMany
        // owner, belongsTo
        // posts, hasMany
        // title, attribute
        ```

        @property fields
        @static
        @type Ember.Map
        @readOnly
      */
      fields: Ember.computed(function() {
        var map = Ember.Map.create();

        this.eachComputedProperty(function(name, meta) {
          if (meta.isRelationship) {
            map.set(name, meta.kind);
          } else if (meta.isAttribute) {
            map.set(name, 'attribute');
          }
        });

        return map;
      }),

      /**
        Given a callback, iterates over each of the relationships in the model,
        invoking the callback with the name of each relationship and its relationship
        descriptor.

        @method eachRelationship
        @static
        @param {Function} callback the callback to invoke
        @param {any} binding the value to which the callback's `this` should be bound
      */
      eachRelationship: function(callback, binding) {
        get(this, 'relationshipsByName').forEach(function(name, relationship) {
          callback.call(binding, name, relationship);
        });
      },

      /**
        Given a callback, iterates over each of the types related to a model,
        invoking the callback with the related type's class. Each type will be
        returned just once, regardless of how many different relationships it has
        with a model.

        @method eachRelatedType
        @static
        @param {Function} callback the callback to invoke
        @param {any} binding the value to which the callback's `this` should be bound
      */
      eachRelatedType: function(callback, binding) {
        get(this, 'relatedTypes').forEach(function(type) {
          callback.call(binding, type);
        });
      }
    });

    Model.reopen({
      /**
        Given a callback, iterates over each of the relationships in the model,
        invoking the callback with the name of each relationship and its relationship
        descriptor.

        @method eachRelationship
        @param {Function} callback the callback to invoke
        @param {any} binding the value to which the callback's `this` should be bound
      */
      eachRelationship: function(callback, binding) {
        this.constructor.eachRelationship(callback, binding);
      }
    });
  });
define("ember-data/lib/system/relationships/has_many", 
  ["../store","../relationship-meta","exports"],
  function(__dependency1__, __dependency2__, __exports__) {
    "use strict";
    /**
      @module ember-data
    */

    var PromiseArray = __dependency1__.PromiseArray;
    var get = Ember.get, set = Ember.set, setProperties = Ember.setProperties;
    var relationshipFromMeta = __dependency2__.relationshipFromMeta;
    var typeForRelationshipMeta = __dependency2__.typeForRelationshipMeta;

    function asyncHasMany(type, options, meta) {
      return Ember.computed('data', function(key) {
        var relationship = this._relationships[key],
            promiseLabel = "DS: Async hasMany " + this + " : " + key;

        meta.key = key;

        if (!relationship) {
          var resolver = Ember.RSVP.defer(promiseLabel);
          relationship = buildRelationship(this, key, options, function(store, data) {
            var link = data.links && data.links[key];
            var rel;
            if (link) {
              rel = store.findHasMany(this, link, relationshipFromMeta(store, meta), resolver);
            } else {
              rel = store.findMany(this, data[key], typeForRelationshipMeta(store, meta), resolver);
            }
            // cache the promise so we can use it
            // when we come back and don't need to rebuild
            // the relationship.
            set(rel, 'promise', resolver.promise);
            return rel;
          });
        }

        var promise = relationship.get('promise').then(function() {
          return relationship;
        }, null, "DS: Async hasMany records received");

        return PromiseArray.create({
          promise: promise
        });
      }).meta(meta).readOnly();
    }

    function buildRelationship(record, key, options, callback) {
      var rels = record._relationships;

      if (rels[key]) { return rels[key]; }

      var data = get(record, 'data'),
          store = get(record, 'store');

      var relationship = rels[key] = callback.call(record, store, data);

      return setProperties(relationship, {
        owner: record,
        name: key,
        isPolymorphic: options.polymorphic
      });
    }

    function hasRelationship(type, options) {
      options = options || {};

      var meta = {
        type: type,
        isRelationship: true,
        options: options,
        kind: 'hasMany',
        key: null
      };

      if (options.async) {
        return asyncHasMany(type, options, meta);
      }

      return Ember.computed('data', function(key) {
        return buildRelationship(this, key, options, function(store, data) {
          var records = data[key];
          Ember.assert("You looked up the '" + key + "' relationship on '" + this + "' but some of the associated records were not loaded. Either make sure they are all loaded together with the parent record, or specify that the relationship is async (`DS.hasMany({ async: true })`)", Ember.A(records).everyProperty('isEmpty', false));
          return store.findMany(this, data[key], typeForRelationshipMeta(store, meta));
        });
      }).meta(meta).readOnly();
    }

    /**
      `DS.hasMany` is used to define One-To-Many and Many-To-Many
      relationships on a [DS.Model](/api/data/classes/DS.Model.html).

      `DS.hasMany` takes an optional hash as a second parameter, currently
      supported options are:

      - `async`: A boolean value used to explicitly declare this to be an async relationship.
      - `inverse`: A string used to identify the inverse property on a related model.

      #### One-To-Many
      To declare a one-to-many relationship between two models, use
      `DS.belongsTo` in combination with `DS.hasMany`, like this:

      ```javascript
      App.Post = DS.Model.extend({
        comments: DS.hasMany('comment')
      });

      App.Comment = DS.Model.extend({
        post: DS.belongsTo('post')
      });
      ```

      #### Many-To-Many
      To declare a many-to-many relationship between two models, use
      `DS.hasMany`:

      ```javascript
      App.Post = DS.Model.extend({
        tags: DS.hasMany('tag')
      });

      App.Tag = DS.Model.extend({
        posts: DS.hasMany('post')
      });
      ```

      #### Explicit Inverses

      Ember Data will do its best to discover which relationships map to
      one another. In the one-to-many code above, for example, Ember Data
      can figure out that changing the `comments` relationship should update
      the `post` relationship on the inverse because post is the only
      relationship to that model.

      However, sometimes you may have multiple `belongsTo`/`hasManys` for the
      same type. You can specify which property on the related model is
      the inverse using `DS.hasMany`'s `inverse` option:

      ```javascript
      var belongsTo = DS.belongsTo,
          hasMany = DS.hasMany;

      App.Comment = DS.Model.extend({
        onePost: belongsTo('post'),
        twoPost: belongsTo('post'),
        redPost: belongsTo('post'),
        bluePost: belongsTo('post')
      });

      App.Post = DS.Model.extend({
        comments: hasMany('comment', {
          inverse: 'redPost'
        })
      });
      ```

      You can also specify an inverse on a `belongsTo`, which works how
      you'd expect.

      @namespace
      @method hasMany
      @for DS
      @param {String or DS.Model} type the model type of the relationship
      @param {Object} options a hash of options
      @return {Ember.computed} relationship
    */
    function hasMany(type, options) {
      if (typeof type === 'object') {
        options = type;
        type = undefined;
      }
      return hasRelationship(type, options);
    }

    __exports__["default"] = hasMany;
  });
define("ember-data/lib/system/store", 
  ["./adapter","ember-inflector/lib/system/string","exports"],
  function(__dependency1__, __dependency2__, __exports__) {
    "use strict";
    /*globals Ember*/
    /*jshint eqnull:true*/

    /**
      @module ember-data
    */

    var InvalidError = __dependency1__.InvalidError;
    var Adapter = __dependency1__.Adapter;
    var singularize = __dependency2__.singularize;
    var get = Ember.get, set = Ember.set;
    var once = Ember.run.once;
    var isNone = Ember.isNone;
    var forEach = Ember.EnumerableUtils.forEach;
    var indexOf = Ember.EnumerableUtils.indexOf;
    var map = Ember.EnumerableUtils.map;
    var Promise = Ember.RSVP.Promise;
    var copy = Ember.copy;
    var Store, PromiseObject, PromiseArray, RecordArrayManager, Model;

    var camelize = Ember.String.camelize;

    // Implementors Note:
    //
    //   The variables in this file are consistently named according to the following
    //   scheme:
    //
    //   * +id+ means an identifier managed by an external source, provided inside
    //     the data provided by that source. These are always coerced to be strings
    //     before being used internally.
    //   * +clientId+ means a transient numerical identifier generated at runtime by
    //     the data store. It is important primarily because newly created objects may
    //     not yet have an externally generated id.
    //   * +reference+ means a record reference object, which holds metadata about a
    //     record, even if it has not yet been fully materialized.
    //   * +type+ means a subclass of DS.Model.

    // Used by the store to normalize IDs entering the store.  Despite the fact
    // that developers may provide IDs as numbers (e.g., `store.find(Person, 1)`),
    // it is important that internally we use strings, since IDs may be serialized
    // and lose type information.  For example, Ember's router may put a record's
    // ID into the URL, and if we later try to deserialize that URL and find the
    // corresponding record, we will not know if it is a string or a number.
    function coerceId(id) {
      return id == null ? null : id+'';
    }

    /**
      The store contains all of the data for records loaded from the server.
      It is also responsible for creating instances of `DS.Model` that wrap
      the individual data for a record, so that they can be bound to in your
      Handlebars templates.

      Define your application's store like this:

      ```javascript
      MyApp.Store = DS.Store.extend();
      ```

      Most Ember.js applications will only have a single `DS.Store` that is
      automatically created by their `Ember.Application`.

      You can retrieve models from the store in several ways. To retrieve a record
      for a specific id, use `DS.Store`'s `find()` method:

      ```javascript
      var person = store.find('person', 123);
      ```

      If your application has multiple `DS.Store` instances (an unusual case), you can
      specify which store should be used:

      ```javascript
      var person = store.find('person', 123);
      ```

      By default, the store will talk to your backend using a standard
      REST mechanism. You can customize how the store talks to your
      backend by specifying a custom adapter:

      ```javascript
       MyApp.store = DS.Store.create({
         adapter: 'MyApp.CustomAdapter'
       });
       ```

      You can learn more about writing a custom adapter by reading the `DS.Adapter`
      documentation.

      ### Store createRecord() vs. push() vs. pushPayload() vs. update()

      The store provides multiple ways to create new records object. They have
      some subtle differences in their use which are detailed below:

      [createRecord](#method_createRecord) is used for creating new
      records on the client side. This will return a new record in the
      `created.uncommitted` state. In order to persist this record to the
      backend you will need to call `record.save()`.

      [push](#method_push) is used to notify Ember Data's store of new or
      updated records that exist in the backend. This will return a record
      in the `loaded.saved` state. The primary use-case for `store#push` is
      to notify Ember Data about record updates that happen
      outside of the normal adapter methods (for example
      [SSE](http://dev.w3.org/html5/eventsource/) or [Web
      Sockets](http://www.w3.org/TR/2009/WD-websockets-20091222/)).

      [pushPayload](#method_pushPayload) is a convenience wrapper for
      `store#push` that will deserialize payloads if the
      Serializer implements a `pushPayload` method.

      [update](#method_update) works like `push`, except it can handle
      partial attributes without overwriting the existing record
      properties.

      Note: When creating a new record using any of the above methods
      Ember Data will update `DS.RecordArray`s such as those returned by
      `store#all()`, `store#findAll()` or `store#filter()`. This means any
      data bindings or computed properties that depend on the RecordArray
      will automatically be synced to include the new or updated record
      values.

      @class Store
      @namespace DS
      @extends Ember.Object
    */
    Store = Ember.Object.extend({

      /**
        @method init
        @private
      */
      init: function() {
        // internal bookkeeping; not observable
        if (!RecordArrayManager) { RecordArrayManager = requireModule("ember-data/lib/system/record_array_manager")["default"]; }
        this.typeMaps = {};
        this.recordArrayManager = RecordArrayManager.create({
          store: this
        });
        this._relationshipChanges = {};
        this._pendingSave = [];
      },

      /**
        The adapter to use to communicate to a backend server or other persistence layer.

        This can be specified as an instance, class, or string.

        If you want to specify `App.CustomAdapter` as a string, do:

        ```js
        adapter: 'custom'
        ```

        @property adapter
        @default DS.RESTAdapter
        @type {DS.Adapter|String}
      */
      adapter: '-rest',

      /**
        Returns a JSON representation of the record using a custom
        type-specific serializer, if one exists.

        The available options are:

        * `includeId`: `true` if the record's ID should be included in
          the JSON representation

        @method serialize
        @private
        @param {DS.Model} record the record to serialize
        @param {Object} options an options hash
      */
      serialize: function(record, options) {
        return this.serializerFor(record.constructor.typeKey).serialize(record, options);
      },

      /**
        This property returns the adapter, after resolving a possible
        string key.

        If the supplied `adapter` was a class, or a String property
        path resolved to a class, this property will instantiate the
        class.

        This property is cacheable, so the same instance of a specified
        adapter class should be used for the lifetime of the store.

        @property defaultAdapter
        @private
        @return DS.Adapter
      */
      defaultAdapter: Ember.computed('adapter', function() {
        var adapter = get(this, 'adapter');

        Ember.assert('You tried to set `adapter` property to an instance of `DS.Adapter`, where it should be a name or a factory', !(adapter instanceof Adapter));

        if (typeof adapter === 'string') {
          adapter = this.container.lookup('adapter:' + adapter) || this.container.lookup('adapter:application') || this.container.lookup('adapter:-rest');
        }

        if (DS.Adapter.detect(adapter)) {
          adapter = adapter.create({
            container: this.container
          });
        }

        return adapter;
      }),

      // .....................
      // . CREATE NEW RECORD .
      // .....................

      /**
        Create a new record in the current store. The properties passed
        to this method are set on the newly created record.

        To create a new instance of `App.Post`:

        ```js
        store.createRecord('post', {
          title: "Rails is omakase"
        });
        ```

        @method createRecord
        @param {String} type
        @param {Object} properties a hash of properties to set on the
          newly created record.
        @return {DS.Model} record
      */
      createRecord: function(type, properties) {
        type = this.modelFor(type);

        properties = copy(properties) || {};

        // If the passed properties do not include a primary key,
        // give the adapter an opportunity to generate one. Typically,
        // client-side ID generators will use something like uuid.js
        // to avoid conflicts.

        if (isNone(properties.id)) {
          properties.id = this._generateId(type);
        }

        // Coerce ID to a string
        properties.id = coerceId(properties.id);

        var record = this.buildRecord(type, properties.id);

        // Move the record out of its initial `empty` state into
        // the `loaded` state.
        record.loadedData();

        // Set the properties specified on the record.
        record.setProperties(properties);

        return record;
      },

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

        @method _generateId
        @private
        @param {String} type
        @return {String} if the adapter can generate one, an ID
      */
      _generateId: function(type) {
        var adapter = this.adapterFor(type);

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

        return null;
      },

      // .................
      // . DELETE RECORD .
      // .................

      /**
        For symmetry, a record can be deleted via the store.

        Example

        ```javascript
        var post = store.createRecord('post', {
          title: "Rails is omakase"
        });

        store.deleteRecord(post);
        ```

        @method deleteRecord
        @param {DS.Model} record
      */
      deleteRecord: function(record) {
        record.deleteRecord();
      },

      /**
        For symmetry, a record can be unloaded via the store. Only
        non-dirty records can be unloaded.

        Example

        ```javascript
        store.find('post', 1).then(function(post) {
          store.unloadRecord(post);
        });
        ```

        @method unloadRecord
        @param {DS.Model} record
      */
      unloadRecord: function(record) {
        record.unloadRecord();
      },

      // ................
      // . FIND RECORDS .
      // ................

      /**
        This is the main entry point into finding records. The first parameter to
        this method is the model's name as a string.

        ---

        To find a record by ID, pass the `id` as the second parameter:

        ```javascript
        store.find('person', 1);
        ```

        The `find` method will always return a **promise** that will be resolved
        with the record. If the record was already in the store, the promise will
        be resolved immediately. Otherwise, the store will ask the adapter's `find`
        method to find the necessary data.

        The `find` method will always resolve its promise with the same object for
        a given type and `id`.

        ---

        To find all records for a type, call `find` with no additional parameters:

        ```javascript
        store.find('person');
        ```

        This will ask the adapter's `findAll` method to find the records for the
        given type, and return a promise that will be resolved once the server
        returns the values.

        ---

        To find a record by a query, call `find` with a hash as the second
        parameter:

        ```javascript
        store.find('person', { page: 1 });
        ```

        This will ask the adapter's `findQuery` method to find the records for
        the query, and return a promise that will be resolved once the server
        responds.

        @method find
        @param {String or subclass of DS.Model} type
        @param {Object|String|Integer|null} id
        @return {Promise} promise
      */
      find: function(type, id) {
        Ember.assert("You need to pass a type to the store's find method", arguments.length >= 1);
        Ember.assert("You may not pass `" + id + "` as id to the store's find method", arguments.length === 1 || !Ember.isNone(id));

        if (arguments.length === 1) {
          return this.findAll(type);
        }

        // We are passed a query instead of an id.
        if (Ember.typeOf(id) === 'object') {
          return this.findQuery(type, id);
        }

        return this.findById(type, coerceId(id));
      },

      /**
        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
      */
      findById: function(type, id) {
        type = this.modelFor(type);

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

        return promiseObject(fetchedRecord || record, "DS: Store#findById " + type + " with id: " + id);
      },

      /**
        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
        @return {Promise} promise
      */
      findByIds: 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"));
      },

      /**
        This method is called by `findById` if it discovers that a particular
        type/id pair hasn't been loaded yet to kick off a request to the
        adapter.

        @method fetchRecord
        @private
        @param {DS.Model} record
        @return {Promise} promise
      */
      fetchRecord: function(record) {
        if (isNone(record)) { return null; }
        if (record._loadingPromise) { return record._loadingPromise; }
        if (!get(record, 'isEmpty')) { return null; }

        var type = record.constructor,
            id = get(record, 'id');

        var adapter = this.adapterFor(type);

        Ember.assert("You tried to find a record but you have no adapter (for " + type + ")", adapter);
        Ember.assert("You tried to find a record but your adapter (for " + type + ") does not implement 'find'", adapter.find);

        var promise = _find(adapter, this, type, id);
        record.loadingData(promise);
        return promise;
      },

      /**
        Get a record by a given type and ID without triggering a fetch.

        This method will synchronously return the record if it's available.
        Otherwise, it will return null.

        ```js
        var post = store.getById('post', 1);
        ```

        @method getById
        @param {String or subclass of DS.Model} type
        @param {String|Integer} id
        @param {DS.Model} record
      */
      getById: function(type, id) {
        if (this.hasRecordForId(type, id)) {
          return this.recordForId(type, id);
        } else {
          return null;
        }
      },

      /**
        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
      */
      reloadRecord: 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 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
        @return {Promise} promise
      */
      fetchMany: function(records, owner) {
        if (!records.length) {
          return Ember.RSVP.resolve(records);
        }

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

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

        var promises = [];

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

          promises.push(_findMany(adapter, this, type, ids, owner));
        }, this);

        return Ember.RSVP.all(promises);
      },

      /**
        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
        @return {Boolean}
      */
      hasRecordForId: function(type, id) {
        id = coerceId(id);
        type = this.modelFor(type);
        return !!this.typeMapFor(type).idToRecord[id];
      },

      /**
        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
        @return {DS.Model} record
      */
      recordForId: 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;
      },

      /**
        @method findMany
        @private
        @param {DS.Model} owner
        @param {Array} records
        @param {String or subclass of DS.Model} type
        @param {Resolver} resolver
        @return {DS.ManyArray} records
      */
      findMany: function(owner, records, type, resolver) {
        type = this.modelFor(type);

        records = Ember.A(records);

        var unloadedRecords = records.filterProperty('isEmpty', true),
            manyArray = this.recordArrayManager.createManyArray(type, records);

        forEach(unloadedRecords, function(record) {
          record.loadingData();
        });

        manyArray.loadingRecordsCount = unloadedRecords.length;

        if (unloadedRecords.length) {
          forEach(unloadedRecords, function(record) {
            this.recordArrayManager.registerWaitingRecordArray(record, manyArray);
          }, this);

          resolver.resolve(this.fetchMany(unloadedRecords, owner));
        } else {
          if (resolver) { resolver.resolve(); }
          manyArray.set('isLoaded', true);
          once(manyArray, 'trigger', 'didLoad');
        }

        return manyArray;
      },

      /**
        If a relationship was originally populated by the adapter as a link
        (as opposed to a list of IDs), this method is called when the
        relationship is fetched.

        The link (which is usually a URL) is passed through unchanged, so the
        adapter can make whatever request it wants.

        The usual use-case is for the server to register a URL as a link, and
        then use that URL in the future to make a request for the relationship.

        @method findHasMany
        @private
        @param {DS.Model} owner
        @param {any} link
        @param {String or subclass of DS.Model} type
        @return {Promise} promise
      */
      findHasMany: function(owner, link, relationship, resolver) {
        var adapter = this.adapterFor(owner.constructor);

        Ember.assert("You tried to load a hasMany relationship but you have no adapter (for " + owner.constructor + ")", adapter);
        Ember.assert("You tried to load a hasMany relationship from a specified `link` in the original payload but your adapter does not implement `findHasMany`", adapter.findHasMany);

        var records = this.recordArrayManager.createManyArray(relationship.type, Ember.A([]));
        resolver.resolve(_findHasMany(adapter, this, owner, link, relationship));
        return records;
      },

      /**
        @method findBelongsTo
        @private
        @param {DS.Model} owner
        @param {any} link
        @param {Relationship} relationship
        @return {Promise} promise
      */
      findBelongsTo: function(owner, link, relationship) {
        var adapter = this.adapterFor(owner.constructor);

        Ember.assert("You tried to load a belongsTo relationship but you have no adapter (for " + owner.constructor + ")", adapter);
        Ember.assert("You tried to load a belongsTo relationship from a specified `link` in the original payload but your adapter does not implement `findBelongsTo`", adapter.findBelongsTo);

        return _findBelongsTo(adapter, this, owner, link, relationship);
      },

      /**
        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
      */
      findQuery: function(type, query) {
        type = this.modelFor(type);

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

        var adapter = this.adapterFor(type);

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

        return promiseArray(_findQuery(adapter, this, type, query, array));
      },

      /**
        This method returns an array of all records adapter can find.
        It triggers the adapter's `findAll` method to give it an opportunity to populate
        the array with records of that type.

        @method findAll
        @private
        @param {String or subclass of DS.Model} type
        @return {DS.AdapterPopulatedRecordArray}
      */
      findAll: function(type) {
        type = this.modelFor(type);

        return this.fetchAll(type, this.all(type));
      },

      /**
        @method fetchAll
        @private
        @param {DS.Model} type
        @param {DS.RecordArray} array
        @return {Promise} promise
      */
      fetchAll: function(type, array) {
        var adapter = this.adapterFor(type),
            sinceToken = this.typeMapFor(type).metadata.since;

        set(array, 'isUpdating', true);

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

        return promiseArray(_findAll(adapter, this, type, sinceToken));
      },

      /**
        @method didUpdateAll
        @param {DS.Model} type
      */
      didUpdateAll: function(type) {
        var findAllCache = this.typeMapFor(type).findAllCache;
        set(findAllCache, 'isUpdating', false);
      },

      /**
        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 localPosts = store.all('post');
        ```

        @method all
        @param {String or subclass of DS.Model} type
        @return {DS.RecordArray}
      */
      all: 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 unloads all of the known records for a given type.

        ```javascript
        store.unloadAll('post');
        ```

        @method unloadAll
        @param {String or subclass of DS.Model} type
      */
      unloadAll: function(type) {
        var modelType = this.modelFor(type);
        var typeMap = this.typeMapFor(modelType);
        var records = typeMap.records.slice();
        var record;

        for (var i = 0; i < records.length; i++) {
          record = records[i];
          record.unloadRecord();
          record.destroy(); // maybe within unloadRecord
        }

        typeMap.findAllCache = null;
      },

      /**
        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('post', {unread: true}, function(post) {
          return post.get('unread');
        }).then(function(unreadPosts) {
          unreadPosts.get('length'); // 5
          var unreadPost = unreadPosts.objectAt(0);
          unreadPost.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}
      */
      filter: function(type, query, filter) {
        var promise;
        var length = arguments.length;
        var array;
        var hasQuery = length === 3;

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

        type = this.modelFor(type);

        if (hasQuery) {
          array = this.recordArrayManager.createFilteredRecordArray(type, filter, query);
        } else {
          array = this.recordArrayManager.createFilteredRecordArray(type, filter);
        }

        promise = promise || Promise.cast(array);


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

      /**
        This method returns if a certain record is already loaded
        in the store. Use this function to know beforehand if a find()
        will result in a request or that it will be a cache hit.

         Example

        ```javascript
        store.recordIsLoaded('post', 1); // false
        store.find('post', 1).then(function() {
          store.recordIsLoaded('post', 1); // true
        });
        ```

        @method recordIsLoaded
        @param {String or subclass of DS.Model} type
        @param {string} id
        @return {boolean}
      */
      recordIsLoaded: function(type, id) {
        if (!this.hasRecordForId(type, id)) { return false; }
        return !get(this.recordForId(type, id), 'isEmpty');
      },

      /**
        This method returns the metadata for a specific type.

        @method metadataFor
        @param {String or subclass of DS.Model} type
        @return {object}
      */
      metadataFor: function(type) {
        type = this.modelFor(type);
        return this.typeMapFor(type).metadata;
      },

      // ............
      // . UPDATING .
      // ............

      /**
        If the adapter updates attributes or acknowledges creation
        or deletion, the record will notify the store to update its
        membership in any filters.
        To avoid thrashing, this method is invoked only once per

        run loop per record.

        @method dataWasUpdated
        @private
        @param {Class} type
        @param {DS.Model} record
      */
      dataWasUpdated: function(type, record) {
        this.recordArrayManager.recordDidChange(record);
      },

      // ..............
      // . PERSISTING .
      // ..............

      /**
        This method is called by `record.save`, and gets passed a
        resolver for the promise that `record.save` returns.

        It schedules saving to happen at the end of the run loop.

        @method scheduleSave
        @private
        @param {DS.Model} record
        @param {Resolver} resolver
      */
      scheduleSave: function(record, resolver) {
        record.adapterWillCommit();
        this._pendingSave.push([record, resolver]);
        once(this, 'flushPendingSave');
      },

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

        @method flushPendingSave
        @private
      */
      flushPendingSave: 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, 'currentState.stateName') === 'root.deleted.saved') {
            return resolver.resolve(record);
          } else 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 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)
      */
      didSaveRecord: function(record, data) {
        if (data) {
          // normalize relationship IDs into records
          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 rejected with a `DS.InvalidError`.

        @method recordWasInvalid
        @private
        @param {DS.Model} record
        @param {Object} errors
      */
      recordWasInvalid: function(record, errors) {
        record.adapterDidInvalidate(errors);
      },

      /**
        This method is called once the promise returned by an
        adapter's `createRecord`, `updateRecord` or `deleteRecord`
        is rejected (with anything other than a `DS.InvalidError`).

        @method recordWasError
        @private
        @param {DS.Model} record
      */
      recordWasError: function(record) {
        record.adapterDidError();
      },

      /**
        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
      */
      updateId: 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);
      },

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

        @method typeMapFor
        @private
        @param type
        @return {Object} typeMap
      */
      typeMapFor: function(type) {
        var typeMaps = get(this, 'typeMaps'),
            guid = Ember.guidFor(type),
            typeMap;

        typeMap = typeMaps[guid];

        if (typeMap) { return typeMap; }

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

        typeMaps[guid] = typeMap;

        return typeMap;
      },

      // ................
      // . LOADING DATA .
      // ................

      /**
        This internal method is used by `push`.

        @method _load
        @private
        @param {String or subclass of DS.Model} type
        @param {Object} data
        @param {Boolean} partial the data should be merged into
          the existing data, not replace it.
      */
      _load: function(type, data, partial) {
        var id = coerceId(data.id),
            record = this.recordForId(type, id);

        record.setupData(data, partial);
        this.recordArrayManager.recordDidChange(record);

        return record;
      },

      /**
        Returns a model class for a particular key. Used by
        methods that take a type key (like `find`, `createRecord`,
        etc.)

        @method modelFor
        @param {String or subclass of DS.Model} key
        @return {subclass of DS.Model}
      */
      modelFor: function(key) {
        var factory;


        if (typeof key === 'string') {
          var normalizedKey = this.container.normalize('model:' + key);

          factory = this.container.lookupFactory(normalizedKey);
          if (!factory) { throw new Ember.Error("No model was found for '" + key + "'"); }
          factory.typeKey = this._normalizeTypeKey(normalizedKey.split(':', 2)[1]);
        } else {
          // A factory already supplied. Ensure it has a normalized key.
          factory = key;
          if (factory.typeKey) {
            factory.typeKey = this._normalizeTypeKey(factory.typeKey);
          }
        }

        factory.store = this;
        return factory;
      },

      /**
        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
        @return {DS.Model} the record that was created or
          updated.
      */
      push: 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` for " + type + " 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 raw data into the store.

        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(pushData);
        ```

        By default, the data will be deserialized using a default
        serializer (the application serializer if it exists).

        Alternativly, `pushPayload` will accept a model type which
        will determine which serializer will process the payload.
        However, the serializer itself (processing this data via
        `normalizePayload`) will not know which model it is
        deserializing.

        ```js
        App.ApplicationSerializer = DS.ActiveModelSerializer;
        App.PostSerializer = DS.JSONSerializer;
        store.pushPayload('comment', pushData); // Will use the ApplicationSerializer
        store.pushPayload('post', pushData); // Will use the PostSerializer
        ```

        @method pushPayload
        @param {String} type Optionally, a model used to determine which serializer will be used
        @param {Object} payload
      */
      pushPayload: 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);
      },

      /**
        Update existing records in the store. Unlike [push](#method_push),
        update will merge the new data properties with the existing
        properties. This makes it safe to use with a subset of record
        attributes. This method expects normalized data.

        `update` is useful if you app broadcasts partial updates to
        records.

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

        store.get('person', 1).then(function(tom) {
          tom.get('firstName'); // Tom
          tom.get('lastName'); // Dale

          var updateEvent = {id: 1, firstName: "TomHuda"};
          store.update('person', updateEvent);

          tom.get('firstName'); // TomHuda
          tom.get('lastName'); // Dale
        });
        ```

        @method update
        @param {String} type
        @param {Object} data
        @return {DS.Model} the record that was updated.
      */
      update: function(type, data) {
        Ember.assert("You must include an `id` for " + type + " in a hash passed to `update`", data.id != null);

        return this.push(type, data, true);
      },

      /**
        If you have an Array of normalized data to push,
        you can call `pushMany` with the Array, and it will
        call `push` repeatedly for you.

        @method pushMany
        @param {String or subclass of DS.Model} type
        @param {Array} datas
        @return {Array}
      */
      pushMany: function(type, datas) {
        return map(datas, function(data) {
          return this.push(type, data);
        }, this);
      },

      /**
        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
      */
      metaForType: function(type, metadata) {
        type = this.modelFor(type);

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

      /**
        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
        @return {DS.Model} record
      */
      buildRecord: 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]);
        Ember.assert("`" + Ember.inspect(type)+ "` does not appear to be an ember-data model", (typeof type._create === 'function') );

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

      // ...............
      // . DESTRUCTION .
      // ...............

      /**
        When a record is destroyed, this un-indexes it and
        removes it from any record arrays so it can be GCed.

        @method dematerializeRecord
        @private
        @param {DS.Model} record
      */
      dematerializeRecord: function(record) {
        var type = record.constructor,
            typeMap = this.typeMapFor(type),
            id = get(record, 'id');

        record.updateRecordArrays();

        if (id) {
          delete typeMap.idToRecord[id];
        }

        var loc = indexOf(typeMap.records, record);
        typeMap.records.splice(loc, 1);
      },

      // ........................
      // . RELATIONSHIP CHANGES .
      // ........................

      addRelationshipChangeFor: function(childRecord, childKey, parentRecord, parentKey, change) {
        var clientId = childRecord.clientId,
            parentClientId = parentRecord ? parentRecord : parentRecord;
        var key = childKey + parentKey;
        var changes = this._relationshipChanges;
        if (!(clientId in changes)) {
          changes[clientId] = {};
        }
        if (!(parentClientId in changes[clientId])) {
          changes[clientId][parentClientId] = {};
        }
        if (!(key in changes[clientId][parentClientId])) {
          changes[clientId][parentClientId][key] = {};
        }
        changes[clientId][parentClientId][key][change.changeType] = change;
      },

      removeRelationshipChangeFor: function(clientRecord, childKey, parentRecord, parentKey, type) {
        var clientId = clientRecord.clientId,
            parentClientId = parentRecord ? parentRecord.clientId : parentRecord;
        var changes = this._relationshipChanges;
        var key = childKey + parentKey;
        if (!(clientId in changes) || !(parentClientId in changes[clientId]) || !(key in changes[clientId][parentClientId])){
          return;
        }
        delete changes[clientId][parentClientId][key][type];
      },

      relationshipChangePairsFor: function(record){
        var toReturn = [];

        if( !record ) { return toReturn; }

        //TODO(Igor) What about the other side
        var changesObject = this._relationshipChanges[record.clientId];
        for (var objKey in changesObject){
          if(changesObject.hasOwnProperty(objKey)){
            for (var changeKey in changesObject[objKey]){
              if(changesObject[objKey].hasOwnProperty(changeKey)){
                toReturn.push(changesObject[objKey][changeKey]);
              }
            }
          }
        }
        return toReturn;
      },

      // ......................
      // . PER-TYPE ADAPTERS
      // ......................

      /**
        Returns the adapter for a given type.

        @method adapterFor
        @private
        @param {subclass of DS.Model} type
        @return DS.Adapter
      */
      adapterFor: function(type) {
        var container = this.container, adapter;

        if (container) {
          adapter = container.lookup('adapter:' + type.typeKey) || container.lookup('adapter:application');
        }

        return adapter || get(this, 'defaultAdapter');
      },

      // ..............................
      // . RECORD CHANGE NOTIFICATION .
      // ..............................

      /**
        Returns an instance of the serializer for a given type. For
        example, `serializerFor('person')` will return an instance of
        `App.PersonSerializer`.

        If no `App.PersonSerializer` is found, this method will look
        for an `App.ApplicationSerializer` (the default serializer for
        your entire application).

        If no `App.ApplicationSerializer` is found, it will fall back
        to an instance of `DS.JSONSerializer`.

        @method serializerFor
        @private
        @param {String} type the record to serialize
        @return {DS.Serializer}
      */
      serializerFor: function(type) {
        type = this.modelFor(type);
        var adapter = this.adapterFor(type);

        return serializerFor(this.container, type.typeKey, adapter && adapter.defaultSerializer);
      },

      willDestroy: function() {
        var typeMaps = this.typeMaps;
        var keys = Ember.keys(typeMaps);
        var store = this;

        var types = map(keys, byType);

        this.recordArrayManager.destroy();

        forEach(types, this.unloadAll, this);

        function byType(entry) {
          return typeMaps[entry]['type'];
        }

      },

      /**
        All typeKeys are camelCase internally. Changing this function may
        require changes to other normalization hooks (such as typeForRoot).

        @method _normalizeTypeKey
        @private
        @param {String} type
        @return {String} if the adapter can generate one, an ID
      */
      _normalizeTypeKey: function(key) {
        return camelize(singularize(key));
      }
    });

    function normalizeRelationships(store, type, data, record) {
      type.eachRelationship(function(key, relationship) {
        // A link (usually a URL) was already provided in
        // normalized form
        if (data.links && data.links[key]) {
          if (record && relationship.options.async) { record._relationships[key] = null; }
          return;
        }

        var kind = relationship.kind,
            value = data[key];

        if (value == null) { return; }

        if (kind === 'belongsTo') {
          deserializeRecordId(store, data, key, relationship, value);
        } else if (kind === 'hasMany') {
          deserializeRecordIds(store, data, key, relationship, value);
          addUnsavedRecords(record, key, value);
        }
      });

      return data;
    }

    function deserializeRecordId(store, data, key, relationship, id) {
      if (!Model) { Model = requireModule("ember-data/lib/system/model")["Model"]; }
      if (isNone(id) || id instanceof Model) {
        return;
      }

      var type;

      if (typeof id === 'number' || typeof id === 'string') {
        type = typeFor(relationship, key, data);
        data[key] = store.recordForId(type, id);
      } else if (typeof id === 'object') {
        // polymorphic
        data[key] = store.recordForId(id.type, id.id);
      }
    }

    function typeFor(relationship, key, data) {
      if (relationship.options.polymorphic) {
        return data[key + "Type"];
      } else {
        return relationship.type;
      }
    }

    function deserializeRecordIds(store, data, key, relationship, ids) {
      for (var i=0, l=ids.length; i<l; i++) {
        deserializeRecordId(store, ids, i, relationship, ids[i]);
      }
    }

    // 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 addUnsavedRecords(record, key, data) {
      if(record) {
        Ember.A(data).pushObjects(record.get(key).filterBy('isNew'));
      }
    }

    // Delegation to the adapter and promise management
    /**
      A `PromiseArray` is an object that acts like both an `Ember.Array`
      and a promise. When the promise is resolved the resulting value
      will be set to the `PromiseArray`'s `content` property. This makes
      it easy to create data bindings with the `PromiseArray` that will be
      updated when the promise resolves.

      For more information see the [Ember.PromiseProxyMixin
      documentation](/api/classes/Ember.PromiseProxyMixin.html).

      Example

      ```javascript
      var promiseArray = DS.PromiseArray.create({
        promise: $.getJSON('/some/remote/data.json')
      });

      promiseArray.get('length'); // 0

      promiseArray.then(function() {
        promiseArray.get('length'); // 100
      });
      ```

      @class PromiseArray
      @namespace DS
      @extends Ember.ArrayProxy
      @uses Ember.PromiseProxyMixin
    */
    PromiseArray = Ember.ArrayProxy.extend(Ember.PromiseProxyMixin);
    /**
      A `PromiseObject` is an object that acts like both an `Ember.Object`
      and a promise. When the promise is resolved the the resulting value
      will be set to the `PromiseObject`'s `content` property. This makes
      it easy to create data bindings with the `PromiseObject` that will
      be updated when the promise resolves.

      For more information see the [Ember.PromiseProxyMixin
      documentation](/api/classes/Ember.PromiseProxyMixin.html).

      Example

      ```javascript
      var promiseObject = DS.PromiseObject.create({
        promise: $.getJSON('/some/remote/data.json')
      });

      promiseObject.get('name'); // null

      promiseObject.then(function() {
        promiseObject.get('name'); // 'Tomster'
      });
      ```

      @class PromiseObject
      @namespace DS
      @extends Ember.ObjectProxy
      @uses Ember.PromiseProxyMixin
    */
    PromiseObject = Ember.ObjectProxy.extend(Ember.PromiseProxyMixin);

    function promiseObject(promise, label) {
      return PromiseObject.create({
        promise: Promise.cast(promise, label)
      });
    }

    function promiseArray(promise, label) {
      return PromiseArray.create({
        promise: Promise.cast(promise, label)
      });
    }

    function isThenable(object) {
      return object && typeof object.then === 'function';
    }

    function serializerFor(container, type, defaultSerializer) {
      return container.lookup('serializer:'+type) ||
                     container.lookup('serializer:application') ||
                     container.lookup('serializer:' + defaultSerializer) ||
                     container.lookup('serializer:-default');
    }

    function defaultSerializer(container) {
      return container.lookup('serializer:application') ||
             container.lookup('serializer:-default');
    }

    function serializerForAdapter(adapter, type) {
      var serializer = adapter.serializer,
          defaultSerializer = adapter.defaultSerializer,
          container = adapter.container;

      if (container && serializer === undefined) {
        serializer = serializerFor(container, type.typeKey, defaultSerializer);
      }

      if (serializer === null || serializer === undefined) {
        serializer = {
          extract: function(store, type, payload) { return payload; }
        };
      }

      return serializer;
    }

    function _find(adapter, store, type, id) {
      var promise = adapter.find(store, type, id),
          serializer = serializerForAdapter(adapter, type),
          label = "DS: Handle Adapter#find of " + type + " with id: " + id;

      return Promise.cast(promise, label).then(function(adapterPayload) {
        Ember.assert("You made a request for a " + type.typeKey + " with id " + id + ", but the adapter's response did not have any data", adapterPayload);
        var payload = serializer.extract(store, type, adapterPayload, id, 'find');

        return store.push(type, payload);
      }, function(error) {
        var record = store.getById(type, id);
        record.notFound();
        throw error;
      }, "DS: Extract payload of '" + type + "'");
    }

    function _findMany(adapter, store, type, ids, owner) {
      var promise = adapter.findMany(store, type, ids, owner),
          serializer = serializerForAdapter(adapter, type),
          label = "DS: Handle Adapter#findMany of " + type;

      return Promise.cast(promise, label).then(function(adapterPayload) {
        var payload = serializer.extract(store, type, adapterPayload, null, 'findMany');

        Ember.assert("The response from a findMany must be an Array, not " + Ember.inspect(payload), Ember.typeOf(payload) === 'array');

        store.pushMany(type, payload);
      }, null, "DS: Extract payload of " + type);
    }

    function _findHasMany(adapter, store, record, link, relationship) {
      var promise = adapter.findHasMany(store, record, link, relationship),
          serializer = serializerForAdapter(adapter, relationship.type),
          label = "DS: Handle Adapter#findHasMany of " + record + " : " + relationship.type;

      return Promise.cast(promise, label).then(function(adapterPayload) {
        var payload = serializer.extract(store, relationship.type, adapterPayload, null, 'findHasMany');

        Ember.assert("The response from a findHasMany must be an Array, not " + Ember.inspect(payload), Ember.typeOf(payload) === 'array');

        var records = store.pushMany(relationship.type, payload);
        record.updateHasMany(relationship.key, records);
      }, null, "DS: Extract payload of " + record + " : hasMany " + relationship.type);
    }

    function _findBelongsTo(adapter, store, record, link, relationship) {
      var promise = adapter.findBelongsTo(store, record, link, relationship),
          serializer = serializerForAdapter(adapter, relationship.type),
          label = "DS: Handle Adapter#findBelongsTo of " + record + " : " + relationship.type;

      return Promise.cast(promise, label).then(function(adapterPayload) {
        var payload = serializer.extract(store, relationship.type, adapterPayload, null, 'findBelongsTo');
        var record = store.push(relationship.type, payload);

        record.updateBelongsTo(relationship.key, record);
        return record;
      }, null, "DS: Extract payload of " + record + " : " + relationship.type);
    }

    function _findAll(adapter, store, type, sinceToken) {
      var promise = adapter.findAll(store, type, sinceToken),
          serializer = serializerForAdapter(adapter, type),
          label = "DS: Handle Adapter#findAll of " + type;

      return Promise.cast(promise, label).then(function(adapterPayload) {
        var payload = serializer.extract(store, type, adapterPayload, null, 'findAll');

        Ember.assert("The response from a findAll must be an Array, not " + Ember.inspect(payload), Ember.typeOf(payload) === 'array');

        store.pushMany(type, payload);
        store.didUpdateAll(type);
        return store.all(type);
      }, null, "DS: Extract payload of findAll " + type);
    }

    function _findQuery(adapter, store, type, query, recordArray) {
      var promise = adapter.findQuery(store, type, query, recordArray),
          serializer = serializerForAdapter(adapter, type),
          label = "DS: Handle Adapter#findQuery of " + type;

      return Promise.cast(promise, label).then(function(adapterPayload) {
        var payload = serializer.extract(store, type, adapterPayload, null, 'findQuery');

        Ember.assert("The response from a findQuery must be an Array, not " + Ember.inspect(payload), Ember.typeOf(payload) === 'array');

        recordArray.load(payload);
        return recordArray;
      }, null, "DS: Extract payload of findQuery " + type);
    }

    function _commit(adapter, store, operation, record) {
      var type = record.constructor,
          promise = adapter[operation](store, type, record),
          serializer = serializerForAdapter(adapter, type),
          label = "DS: Extract and notify about " + operation + " completion of " + record;

      Ember.assert("Your adapter's '" + operation + "' method must return a promise, but it returned " + promise, isThenable(promise));

      return promise.then(function(adapterPayload) {
        var payload;

        if (adapterPayload) {
          payload = serializer.extract(store, type, adapterPayload, get(record, 'id'), operation);
        } else {
          payload = adapterPayload;
        }

        store.didSaveRecord(record, payload);
        return record;
      }, function(reason) {
        if (reason instanceof InvalidError) {
          store.recordWasInvalid(record, reason.errors);
        } else {
          store.recordWasError(record, reason);
        }

        throw reason;
      }, label);
    }

    __exports__.Store = Store;
    __exports__.PromiseArray = PromiseArray;
    __exports__.PromiseObject = PromiseObject;
    __exports__["default"] = Store;
  });
define("ember-data/lib/transforms", 
  ["./transforms/base","./transforms/number","./transforms/date","./transforms/string","./transforms/boolean","exports"],
  function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
    "use strict";
    var Transform = __dependency1__["default"];
    var NumberTransform = __dependency2__["default"];
    var DateTransform = __dependency3__["default"];
    var StringTransform = __dependency4__["default"];
    var BooleanTransform = __dependency5__["default"];

    __exports__.Transform = Transform;
    __exports__.NumberTransform = NumberTransform;
    __exports__.DateTransform = DateTransform;
    __exports__.StringTransform = StringTransform;
    __exports__.BooleanTransform = BooleanTransform;
  });
define("ember-data/lib/transforms/base", 
  ["exports"],
  function(__exports__) {
    "use strict";
    /**
      The `DS.Transform` class is used to serialize and deserialize model
      attributes when they are saved or loaded from an
      adapter. Subclassing `DS.Transform` is useful for creating custom
      attributes. All subclasses of `DS.Transform` must implement a
      `serialize` and a `deserialize` method.

      Example

      ```javascript
      // Converts centigrade in the JSON to fahrenheit in the app
      App.TemperatureTransform = DS.Transform.extend({
        deserialize: function(serialized) {
          return (serialized *  1.8) + 32;
        },
        serialize: function(deserialized) {
          return (deserialized - 32) / 1.8;
        }
      });
      ```

      Usage

      ```javascript
      var attr = DS.attr;
      App.Requirement = DS.Model.extend({
        name: attr('string'),
        optionsArray: attr('raw')
      });
      ```

      @class Transform
      @namespace DS
     */
    var Transform = Ember.Object.extend({
      /**
        When given a deserialized value from a record attribute this
        method must return the serialized value.

        Example

        ```javascript
        serialize: function(deserialized) {
          return Ember.isEmpty(deserialized) ? null : Number(deserialized);
        }
        ```

        @method serialize
        @param deserialized The deserialized value
        @return The serialized value
      */
      serialize: Ember.required(),

      /**
        When given a serialize value from a JSON object this method must
        return the deserialized value for the record attribute.

        Example

        ```javascript
        deserialize: function(serialized) {
          return empty(serialized) ? null : Number(serialized);
        }
        ```

        @method deserialize
        @param serialized The serialized value
        @return The deserialized value
      */
      deserialize: Ember.required()

    });

    __exports__["default"] = Transform;
  });
define("ember-data/lib/transforms/boolean", 
  ["./base","exports"],
  function(__dependency1__, __exports__) {
    "use strict";
    var Transform = __dependency1__["default"];

    /**
      The `DS.BooleanTransform` class is used to serialize and deserialize
      boolean attributes on Ember Data record objects. This transform is
      used when `boolean` is passed as the type parameter to the
      [DS.attr](../../data#method_attr) function.

      Usage

      ```javascript
      var attr = DS.attr;
      App.User = DS.Model.extend({
        isAdmin: attr('boolean'),
        name: attr('string'),
        email: attr('string')
      });
      ```

      @class BooleanTransform
      @extends DS.Transform
      @namespace DS
     */
    var BooleanTransform = Transform.extend({
      deserialize: function(serialized) {
        var type = typeof serialized;

        if (type === "boolean") {
          return serialized;
        } else if (type === "string") {
          return serialized.match(/^true$|^t$|^1$/i) !== null;
        } else if (type === "number") {
          return serialized === 1;
        } else {
          return false;
        }
      },

      serialize: function(deserialized) {
        return Boolean(deserialized);
      }
    });
    __exports__["default"] = BooleanTransform;
  });
define("ember-data/lib/transforms/date", 
  ["./base","exports"],
  function(__dependency1__, __exports__) {
    "use strict";
    /**
      The `DS.DateTransform` class is used to serialize and deserialize
      date attributes on Ember Data record objects. This transform is used
      when `date` is passed as the type parameter to the
      [DS.attr](../../data#method_attr) function.

      ```javascript
      var attr = DS.attr;
      App.Score = DS.Model.extend({
        value: attr('number'),
        player: DS.belongsTo('player'),
        date: attr('date')
      });
      ```

      @class DateTransform
      @extends DS.Transform
      @namespace DS
     */
    var Transform = __dependency1__["default"];
    var DateTransform = Transform.extend({

      deserialize: function(serialized) {
        var type = typeof serialized;

        if (type === "string") {
          return new Date(Ember.Date.parse(serialized));
        } else if (type === "number") {
          return new Date(serialized);
        } else if (serialized === null || serialized === undefined) {
          // if the value is not present in the data,
          // return undefined, not null.
          return serialized;
        } else {
          return null;
        }
      },

      serialize: function(date) {
        if (date instanceof Date) {
          var days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
          var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];

          var pad = function(num) {
            return num < 10 ? "0"+num : ""+num;
          };

          var utcYear = date.getUTCFullYear(),
              utcMonth = date.getUTCMonth(),
              utcDayOfMonth = date.getUTCDate(),
              utcDay = date.getUTCDay(),
              utcHours = date.getUTCHours(),
              utcMinutes = date.getUTCMinutes(),
              utcSeconds = date.getUTCSeconds();


          var dayOfWeek = days[utcDay];
          var dayOfMonth = pad(utcDayOfMonth);
          var month = months[utcMonth];

          return dayOfWeek + ", " + dayOfMonth + " " + month + " " + utcYear + " " +
                 pad(utcHours) + ":" + pad(utcMinutes) + ":" + pad(utcSeconds) + " GMT";
        } else {
          return null;
        }
      } 

    });

    __exports__["default"] = DateTransform;
  });
define("ember-data/lib/transforms/number", 
  ["./base","exports"],
  function(__dependency1__, __exports__) {
    "use strict";
    var Transform = __dependency1__["default"];

    var empty = Ember.isEmpty;

    /**
      The `DS.NumberTransform` class is used to serialize and deserialize
      numeric attributes on Ember Data record objects. This transform is
      used when `number` is passed as the type parameter to the
      [DS.attr](../../data#method_attr) function.

      Usage

      ```javascript
      var attr = DS.attr;
      App.Score = DS.Model.extend({
        value: attr('number'),
        player: DS.belongsTo('player'),
        date: attr('date')
      });
      ```

      @class NumberTransform
      @extends DS.Transform
      @namespace DS
     */
    var NumberTransform = Transform.extend({

      deserialize: function(serialized) {
        return empty(serialized) ? null : Number(serialized);
      },

      serialize: function(deserialized) {
        return empty(deserialized) ? null : Number(deserialized);
      }
    });

    __exports__["default"] = NumberTransform;
  });
define("ember-data/lib/transforms/string", 
  ["./base","exports"],
  function(__dependency1__, __exports__) {
    "use strict";
    var Transform = __dependency1__["default"];
    var none = Ember.isNone;

    /**
      The `DS.StringTransform` class is used to serialize and deserialize
      string attributes on Ember Data record objects. This transform is
      used when `string` is passed as the type parameter to the
      [DS.attr](../../data#method_attr) function.

      Usage

      ```javascript
      var attr = DS.attr;
      App.User = DS.Model.extend({
        isAdmin: attr('boolean'),
        name: attr('string'),
        email: attr('string')
      });
      ```

      @class StringTransform
      @extends DS.Transform
      @namespace DS
     */
    var StringTransform = Transform.extend({

      deserialize: function(serialized) {
        return none(serialized) ? null : String(serialized);
      },

      serialize: function(deserialized) {
        return none(deserialized) ? null : String(deserialized);
      }

    });

    __exports__["default"] = StringTransform;
  });
define("ember-inflector/lib/ext/string", 
  ["../system/string"],
  function(__dependency1__) {
    "use strict";
    var pluralize = __dependency1__.pluralize;
    var singularize = __dependency1__.singularize;

    if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.String) {
      /**
        See {{#crossLink "Ember.String/pluralize"}}{{/crossLink}}

        @method pluralize
        @for String
      */
      String.prototype.pluralize = function() {
        return pluralize(this);
      };

      /**
        See {{#crossLink "Ember.String/singularize"}}{{/crossLink}}

        @method singularize
        @for String
      */
      String.prototype.singularize = function() {
        return singularize(this);
      };
    }
  });
define("ember-inflector/lib/main", 
  ["./system","./ext/string","exports"],
  function(__dependency1__, __dependency2__, __exports__) {
    "use strict";
    var Inflector = __dependency1__.Inflector;
    var defaultRules = __dependency1__.defaultRules;
    var pluralize = __dependency1__.pluralize;
    var singularize = __dependency1__.singularize;

    Inflector.defaultRules = defaultRules;
    Ember.Inflector        = Inflector;

    Ember.String.pluralize   = pluralize;
    Ember.String.singularize = singularize;


    __exports__["default"] = Inflector;

    __exports__.pluralize = pluralize;
    __exports__.singularize = singularize;
  });
define("ember-inflector/lib/system", 
  ["./system/inflector","./system/string","./system/inflections","exports"],
  function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
    "use strict";
    var Inflector = __dependency1__["default"];

    var pluralize = __dependency2__.pluralize;
    var singularize = __dependency2__.singularize;

    var defaultRules = __dependency3__["default"];

    
    Inflector.inflector = new Inflector(defaultRules);
    
    __exports__.Inflector = Inflector;
    __exports__.singularize = singularize;
    __exports__.pluralize = pluralize;
    __exports__.defaultRules = defaultRules;
  });
define("ember-inflector/lib/system/inflections", 
  ["exports"],
  function(__exports__) {
    "use strict";
    var defaultRules = {
      plurals: [
        [/$/, 's'],
        [/s$/i, 's'],
        [/^(ax|test)is$/i, '$1es'],
        [/(octop|vir)us$/i, '$1i'],
        [/(octop|vir)i$/i, '$1i'],
        [/(alias|status)$/i, '$1es'],
        [/(bu)s$/i, '$1ses'],
        [/(buffal|tomat)o$/i, '$1oes'],
        [/([ti])um$/i, '$1a'],
        [/([ti])a$/i, '$1a'],
        [/sis$/i, 'ses'],
        [/(?:([^f])fe|([lr])f)$/i, '$1$2ves'],
        [/(hive)$/i, '$1s'],
        [/([^aeiouy]|qu)y$/i, '$1ies'],
        [/(x|ch|ss|sh)$/i, '$1es'],
        [/(matr|vert|ind)(?:ix|ex)$/i, '$1ices'],
        [/^(m|l)ouse$/i, '$1ice'],
        [/^(m|l)ice$/i, '$1ice'],
        [/^(ox)$/i, '$1en'],
        [/^(oxen)$/i, '$1'],
        [/(quiz)$/i, '$1zes']
      ],

      singular: [
        [/s$/i, ''],
        [/(ss)$/i, '$1'],
        [/(n)ews$/i, '$1ews'],
        [/([ti])a$/i, '$1um'],
        [/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)(sis|ses)$/i, '$1sis'],
        [/(^analy)(sis|ses)$/i, '$1sis'],
        [/([^f])ves$/i, '$1fe'],
        [/(hive)s$/i, '$1'],
        [/(tive)s$/i, '$1'],
        [/([lr])ves$/i, '$1f'],
        [/([^aeiouy]|qu)ies$/i, '$1y'],
        [/(s)eries$/i, '$1eries'],
        [/(m)ovies$/i, '$1ovie'],
        [/(x|ch|ss|sh)es$/i, '$1'],
        [/^(m|l)ice$/i, '$1ouse'],
        [/(bus)(es)?$/i, '$1'],
        [/(o)es$/i, '$1'],
        [/(shoe)s$/i, '$1'],
        [/(cris|test)(is|es)$/i, '$1is'],
        [/^(a)x[ie]s$/i, '$1xis'],
        [/(octop|vir)(us|i)$/i, '$1us'],
        [/(alias|status)(es)?$/i, '$1'],
        [/^(ox)en/i, '$1'],
        [/(vert|ind)ices$/i, '$1ex'],
        [/(matr)ices$/i, '$1ix'],
        [/(quiz)zes$/i, '$1'],
        [/(database)s$/i, '$1']
      ],

      irregularPairs: [
        ['person', 'people'],
        ['man', 'men'],
        ['child', 'children'],
        ['sex', 'sexes'],
        ['move', 'moves'],
        ['cow', 'kine'],
        ['zombie', 'zombies']
      ],

      uncountable: [
        'equipment',
        'information',
        'rice',
        'money',
        'species',
        'series',
        'fish',
        'sheep',
        'jeans',
        'police'
      ]
    };

    __exports__["default"] = defaultRules;
  });
define("ember-inflector/lib/system/inflector", 
  ["exports"],
  function(__exports__) {
    "use strict";
    var BLANK_REGEX = /^\s*$/;

    function loadUncountable(rules, uncountable) {
      for (var i = 0, length = uncountable.length; i < length; i++) {
        rules.uncountable[uncountable[i].toLowerCase()] = true;
      }
    }

    function loadIrregular(rules, irregularPairs) {
      var pair;

      for (var i = 0, length = irregularPairs.length; i < length; i++) {
        pair = irregularPairs[i];

        rules.irregular[pair[0].toLowerCase()] = pair[1];
        rules.irregularInverse[pair[1].toLowerCase()] = pair[0];
      }
    }

    /**
      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
    */
    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.prototype = {
      /**
        @method plural
        @param {RegExp} regex
        @param {String} string
      */
      plural: function(regex, string) {
        this.rules.plurals.push([regex, string.toLowerCase()]);
      },

      /**
        @method singular
        @param {RegExp} regex
        @param {String} string
      */
      singular: function(regex, string) {
        this.rules.singular.push([regex, string.toLowerCase()]);
      },

      /**
        @method uncountable
        @param {String} regex
      */
      uncountable: function(string) {
        loadUncountable(this.rules, [string.toLowerCase()]);
      },

      /**
        @method irregular
        @param {String} singular
        @param {String} plural
      */
      irregular: function (singular, plural) {
        loadIrregular(this.rules, [[singular, plural]]);
      },

      /**
        @method pluralize
        @param {String} word
      */
      pluralize: function(word) {
        return this.inflect(word, this.rules.plurals, this.rules.irregular);
      },

      /**
        @method singularize
        @param {String} word
      */
      singularize: function(word) {
        return this.inflect(word, this.rules.singular,  this.rules.irregularInverse);
      },

      /**
        @protected

        @method inflect
        @param {String} word
        @param {Object} typeRules
        @param {Object} irregular
      */
      inflect: function(word, typeRules, irregular) {
        var inflection, substitution, result, lowercase, isBlank,
        isUncountable, isIrregular, isIrregularInverse, rule;

        isBlank = BLANK_REGEX.test(word);

        if (isBlank) {
          return word;
        }

        lowercase = word.toLowerCase();

        isUncountable = this.rules.uncountable[lowercase];

        if (isUncountable) {
          return word;
        }

        isIrregular = irregular && irregular[lowercase];

        if (isIrregular) {
          return isIrregular;
        }

        for (var i = typeRules.length, min = 0; i > min; i--) {
           inflection = typeRules[i-1];
           rule = inflection[0];

          if (rule.test(word)) {
            break;
          }
        }

        inflection = inflection || [];

        rule = inflection[0];
        substitution = inflection[1];

        result = word.replace(rule, substitution);

        return result;
      }
    };

    __exports__["default"] = Inflector;
  });
define("ember-inflector/lib/system/string", 
  ["./inflector","exports"],
  function(__dependency1__, __exports__) {
    "use strict";
    var Inflector = __dependency1__["default"];
    var pluralize = function(word) {
      return Inflector.inflector.pluralize(word);
    };

    var singularize = function(word) {
      return Inflector.inflector.singularize(word);
    };

    __exports__.pluralize = pluralize;
    __exports__.singularize = singularize;
  });
global.DS = requireModule('ember-data/lib/main')['default'];
}(Ember.lookup));