Deprecations Added in Ember Data 2.x

What follows is a list of deprecations introduced to Ember Data during the 2.x cycle.

For more information on deprecations in Ember Data, see the main deprecations page.

Deprecations Added in 2.3

§ Non-primitive defaultValue for Model Attributes

until: 3.0.0
id: non-primitive-defaultvalue-for-model-attributes

Providing a non-primitive value as a defaultValue has been deprecated because the provided value is shared between all instances of the model. Using a non-primitive value, such as defaultValue: [], can lead to unexpected bugs when that value is mutated.

If you wish to continue using a non-primitive value as the defaultValue for an attribute, you should provide a function that returns the value:

import DS from 'ember-data';

export default DS.Model.extend({
  username: DS.attr('string'),
  createdAt: DS.attr('date', {
    defaultValue() {
      return new Date();
    }
  })
});

§ RESTSerializer.keyForPolymorphicType

until: 3.0.0
id: restserializer-keyforpolymorphictype

Previous versions of the RESTSerializer relied on keyForAttribute to determine the type key used for serializing polymorphic relationships. This behavior has been deprecated in favor of using keyForPolymorphicType. The benefit of having this additional hook is that you can customize the type key separately from the key used for the relationship.

For example, given the following model:

app/models/comment.js
import DS from 'ember-data';

export default DS.Model.extend({
  commentable: belongsTo('commentable', { polymorphic: true }),
  body: DS.attr('string')
});

When using the RESTSerializer, Ember Data expects a payload that looks similar the following:

{
  "comment": {
    "id": "1",
    "commentable": "123",
    "commentableType": "movie", // ${keyForAttribute}Type
    "body": "I'll be back"
  },
  "movie": {
    "id": "123",
    "title": "The Terminator"
  }
}

If your API instead responds with a key that doesn't follow the pattern of ${keyForAttribute}Type:

{
  "comment": {
    "id": "1",
    "commentable": "123",
    "commentKind": "movie", // custom keyForPolymorphicType needed
    "body": "I'll be back"
  },
  "movie": {
    "id": "123",
    "title": "The Terminator"
  }
}

You can now override the keyForPolymorphicType hook in your serializer to accommodate:

import DS from 'ember-data';

export default DS.RESTSerializer.extend({
  keyForPolymorphicType: function() {
    return 'commentKind';
  }
});

Deprecations Added in 2.6

§ RESTSerializer.normalizeHash

until: 3.0.0
id: restserializer-normalizehash

RESTSerializer.normalizeHash has been deprecated in favor of using normalize.

If you had this:

import DS from 'ember-data';

export default DS.RESTSerializer.extend({
  normalizeHash: {
    _id: function(hash) {
      hash.id = hash._id;
      delete hash._id;
      return hash;
    }
  }
});

You could change it to this:

import DS from 'ember-data';

export default DS.RESTSerializer.extend({
  normalize(model, hash, prop) {
    if (prop === 'comments') {
      hash.id = hash._id;
      delete hash._id;
    }
    return this._super(...arguments);
  }
});

Deprecations Added in 2.7

§ Date Prototype Extension

until: 3.0.0
id: date-prototype-extension

In previous versions of Ember Data, the native Date.parse function was replaced with Ember.Date.parse, a progressive enhancement for ISO 8601 support in browsers that do not support it (Safari 5-, IE 8-, Firefox 3.6-). Since these browser versions are no longer supported by Ember or Ember data, this behavior has been deprecated.

To clear this deprecation, you should disable Ember Data's Date prototype extension.

With Ember >= v2.7.0, disable the prototype extension for Date:

config/environment.js
ENV = {
  EmberENV: {
    EXTEND_PROTOTYPES: {
      Date: false
    }
  }
}

With Ember < v2.7.0, values must be provided for all prototype extensions:

config/environment.js
var ENV = {
  EmberENV: {
    EXTEND_PROTOTYPES: {
      Array: true,
      Date: false,
      Function: true,
      String: true
    }
  }
};

If you're not sure which prototype extensions your app already has enabled, you can check EmberENV.EXTEND_PROTOTYPES in your browser's JavaScript console while your app is running.

See Disabling Prototype Extensions for more information about how Ember uses prototype extensions.

§ Global version of DS

until: 3.0.0
id: global-version-of-ds

Using the global version of DS is deprecated. Import DS or specific modules from ember-data where needed.

For example, if you had:

/* globals DS */

It would be refactored to:

import DS from 'ember-data';

§ Ember.Date.parse

until: 3.0.0
id: ember-date-parse

Ember.Date.parse was created as a progressive enhancement for ISO 8601 support in browsers that do not support it (Safari 5-, IE 8-, Firefox 3.6-). These browsers versions are no longer supported by Ember or Ember Data so Ember.Date.parse has been deprecated.

To clear this deprecation you should refactor your application's code to use Date.parse instead of Ember.Date.parse.

§ Store.queryRecord Array Response with RESTSerializer

until: 3.0.0
id: store-queryrecord-array-response-with-restserializer

When using DS.RESTSerializer with previous versions of Ember Data, store.queryRecord provided support for normalizing payloads containing an array of primary data. This behavior has been deprecated because it is basically the same as using store.query and returning the first model.

Deprecated payload example with an array as the primary data:

// GET /users?username="GummyBear"

{
  "users": [{
    "id": "1",
    "username": "GummyBear"
  }]
}

Expected payload example with a single object as the primary data:

// GET /users?username="GummyBear"

{
  "user": {
    "id": "1",
    "username": "GummyBear",
  }
}

If you need to support an API that responds with an array as the primary data, you have a few options. The simplest option is to use store.query instead of store.queryRecord:

this.store.query('user', { username: 'GummyBear' }).then((users) => {
  return users.objectAt(0);
});

Another option is to override normalizeQueryRecordResponse in your serializer, manipulating the payload so it matches the expected format:

app/serializers/user.js
import DS from 'ember-data';

export default DS.RESTSerializer.extend({
  normalizeQueryRecordResponse(store, primaryModelClass, payload) {
    if (payload.users) {
      payload.user = payload.users[0];
      delete payload.users;
    }

    return this._super(...arguments);
  }
});

Another option is to customize the URL of the request made by store.queryRecord so that it makes a request that returns the expected payload with a single object as its primary data. This can be done by overriding urlForQueryRecord in your adapter:

app/adapters/user.js
import DS from 'ember-data';

export default DS.RESTAdapter.extend({
  urlForQueryRecord() {
    let baseURL = this.buildURL();
    return `${baseURL}/user-query`;
  }
});

Deprecations Added in 2.11

§ lookupAdapter

until: 3.0.0
id: lookupadapter

lookupAdapter has been deprecated in favor of using adapterFor.

§ lookupSerializer

until: 3.0.0
id: lookupserializer

lookupSerializer has been deprecated in favor of using serializerFor.

§ recordIsLoaded

until: 3.0.0
id: recordisloaded

recordIsLoaded has been deprecated and is an alias for hasRecordForId, which should be used instead.

If you have this:

store.recordIsLoaded('post', 1); // false
store.findRecord('post', 1).then(function() {
  store.recordIsLoaded('post', 1); // true
});

You can change it to this:

store.hasRecordForId('post', 1); // false
store.findRecord('post', 1).then(function() {
  store.hasRecordForId('post', 1); // true
});

When using DS.RESTSerializer with previous versions of Ember Data, store.queryRecord provided support for normalizing payloads containing an array of primary data. This behavior has been deprecated because it is basically the same as using store.query and returning the first model.

Deprecated payload example with an array as the primary data:

// GET /users?username="GummyBear"

{
  "users": [{
    "id": "1",
    "username": "GummyBear"
  }]
}

Expected payload example with a single object as the primary data:

// GET /users?username="GummyBear"

{
  "user": {
    "id": "1",
    "username": "GummyBear",
  }
}

If you need to support an API that responds with an array as the primary data, you have a few options. The simplest option is to use store.query instead of store.queryRecord:

this.store.query('user', { username: 'GummyBear' }).then((users) => {
  return users.objectAt(0);
});

Another option is to override normalizeQueryRecordResponse in your serializer, manipulating the payload so it matches the expected format:

app/serializers/user.js
import DS from 'ember-data';

export default DS.RESTSerializer.extend({
  normalizeQueryRecordResponse(store, primaryModelClass, payload) {
    if (payload.users) {
      payload.user = payload.users[0];
      delete payload.users;
    }

    return this._super(...arguments);
  }
});

Another option is to customize the URL of the request made by store.queryRecord so that it makes a request that returns the expected payload with a single object as its primary data. This can be done by overriding urlForQueryRecord in your adapter:

app/adapters/user.js
import DS from 'ember-data';

export default DS.RESTAdapter.extend({
  urlForQueryRecord() {
    let baseURL = this.buildURL();
    return `${baseURL}/user-query`;
  }
});

§ Store.serialize

until: 3.0.0
id: store-serialize

Store.serialize has been deprecated in favor of Model.serialize as part of an effort to reduce duplication and API surface area.

Before:

let post = this.store.peekRecord('post', 123);
this.store.serialize(post);

After:

let post = this.store.peekRecord('post', 123);

post.serialize();

Deprecations Added in 2.12

§ JSONSerializer.shouldSerializeHasMany

until: 3.0.0
id: jsonserializer-shouldserializehasmany

The private method _shouldSerializeHasMany has been promoted to the public API. To remove this deprecation, please remove the underscore to use the public shouldSerializeHasMany method.

Deprecations Added in 2.13

§ Unused Initializers

until: 3.0.0
id: unused-initializers

The Ember Data initializers data-adapter, injectStore, transforms, and store are no longer used, so they are being removed. Applications that depend on these for the ordering of their own custom initializers can substitute ember-data instead, without any change in functionality.

Before:

export function initialize(application) {
  // ... your code ...
};

export default {
  name: 'websocketInit',
  after: 'store',
  initialize: initialize
};

After:

export function initialize(application) {
  // ... your code ...
};

export default {
  name: 'websocketInit',
  after: 'ember-data',
  initialize: initialize
};

Deprecations Added in Upcoming Features

§ JSONAPISerializer.modelNameFromPayloadKey for Resource

until: 4.0.0
id: jsonapiserializer-modelnamefrompayloadkey-for-resource

feature: ds-payload-type-hooks

Using JSONAPISerializer.modelNameFromPayloadKey to normalize the type of a resource has been deprecated in favor of JSONAPISerializer.modelNameFromPayloadType.

In the context of a JSON API payload, it is the value of the type key that maps to the name of the corresponding DS.Model class rather than the key that the data is nested under.

For example, if your API responds with a namespaced resource type in the payload when you fetch a post:

// GET /post/1

{
  "data": {
    "type": "api::v1::post",
    "id": "1"
  }
}

Previously, you would want to override modelNameFromPayloadKey to remove the namespace:

app/serializers/post.js
import DS from 'ember-data';

export default DS.JSONAPISerializer.extend({
  payloadKeyFromModelName(modelName) {
    return `api::v1::${modelName}`;
  }
});

You can remove this deprecation by refactoring your serializer to instead use payloadTypeFromModelName:

app/serializers/post.js
import DS from 'ember-data';

export default DS.JSONAPISerializer.extend({
  payloadTypeFromModelName(modelName) {
    return `api::v1::${modelName}`;
  }
});

§ JSONAPISerializer.payloadKeyFromModelName for belongsTo Relationship

until: 4.0.0
id: jsonapiserializer-payloadkeyfrommodelname-for-belongsto-relationship

feature: ds-payload-type-hooks

Using JSONAPISerializer.payloadKeyFromModelName to serialize the type of a belongsTo relationship has been deprecated in favor of JSONAPISerializer.payloadTypeFromModelName.

See JSONAPISerializer.payloadKeyFromModelName for Resource for more information.

§ JSONAPISerializer.payloadKeyFromModelName for hasMany Relationship

until: 4.0.0
id: jsonapiserializer-payloadkeyfrommodelname-for-hasmany-relationship

feature: ds-payload-type-hooks

Using JSONAPISerializer.payloadKeyFromModelName to serialize the type of a hasMany relationship has been deprecated in favor of JSONAPISerializer.payloadTypeFromModelName.

see jsonapiserializer.payloadkeyfrommodelname for Resource for more information.

§ JSONAPISerializer.modelNameFromPayloadKey for Relationship

until: 4.0.0
id: jsonapiserializer-modelnamefrompayloadkey-for-relationship

feature: ds-payload-type-hooks

Using JSONAPISerializer.modelNameFromPayloadKey to normalize the type of a relationship has been deprecated in favor of JSONAPISerializer.modelNameFromPayloadType.

See JSONAPISerializer.modelNameFromPayloadKey for Resource for more information.

§ JSONAPISerializer.payloadKeyFromModelName for Resource

until: 4.0.0
id: jsonapiserializer-payloadkeyfrommodelname-for-resource

feature: ds-payload-type-hooks

Using JSONAPISerializer.payloadKeyFromModelName to serialize the type of a model has been deprecated in favor of JSONAPISerializer.payloadTypeFromModelName.

For example, if your API expects a namespaced resource type in the payload that is sent when you create a post model:

// POST /api/posts/1

{
  "data": {
    "id": 1,
    "type": "api::v1::post"
  }
}

Previously, you would want to override payloadKeyFromModelName to add the namespace to the modelName:

app/serializers/post.js
import DS from 'ember-data';

export default DS.JSONAPISerializer.extend({
  payloadKeyFromModelName(modelName) {
    return `api::v1::${modelName}`;
  }
});

You can remove this deprecation by refactoring your serializer to instead use payloadTypeFromModelName:

app/serializers/post.js
import DS from 'ember-data';

export default DS.JSONAPISerializer.extend({
  payloadTypeFromModelName(modelName) {
    return `api::v1::${modelName}`;
  }
});

§ BelongsToReference.push(DS.Model)

until: 4.0.0
id: ds.references.belongs-to.push-record

feature: ds-overhaul-references

Passing an instance of DS.Model to BelongsToReference#push has been deprecated. You should instead follow the pattern of model.set('relationship', value) to update a belongsTo relationship with an instance of DS.Model.

For example, if you have something like:

let post = this.store.peekRecord('post', 123);
let author = this.store.peekRecord('user', 456);

post.belongsTo('author').push(author);

You can remove this deprecation by refactoring your code to:

let post = this.store.peekRecord('post', 123);
let author = this.store.peekRecord('user', 456);

post.set('author', author);

§ HasManyReference.push(array)

until: 4.0.0
id: hasmanyreference-push-array

feature: ds-overhaul-references

Deprecations Added in Pending Features

Passing an array to a HasManyReference#push has been deprecated. You should refactor your code to instead pass a JSON API Relationship Object.

For example, if you previously had something like:

let commentsData = [
  { data: { type: 'comment', id: 1 } },
  { data: { type: 'comment', id: 2 } }
];

let post = this.store.peekRecord('post', 123);

post.hasMany('comments').push(commentsData);

You could remove this deprecation by refactoring your code to:

let commentsData = {
  data: [
    { type: 'comment', id: 1 },
    { type: 'comment', id: 2 }
  ]
};

let post = this.store.peekRecord('post', 123);

post.hasMany('comments').push(commentsData);

§ HasManyReference.push Invalid Data

until: 4.0.0
id: hasmanyreference-push-invalid-data

feature: ds-overhaul-references

In previous versions of Ember Data, HasManyReference#push supported pushing data that was almost formatted as a JSON API Relationship Object, but wasn't quite correct. Pushing data that is formatted this way has been deprecated. You should refactor your code to instead push a properly formatted JSON API Relationship Object.

For example, if you previously had something like:

let commentsData = {
  data: [
    { data: { type: 'comment', id: 1 } },
    { data: { type: 'comment', id: 2 } }
  ]
};

let post = this.store.peekRecord('post', 123);

post.hasMany('comments').push(commentsData);

You could remove this deprecation by refactoring your code to:

let commentsData = {
  data: [
    { type: 'comment', id: 1 },
    { type: 'comment', id: 2 }
  ]
};

let post = this.store.peekRecord('post', 123);

post.hasMany('comments').push(commentsData);