Deprecations Added in Ember Data 3.x

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

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

Deprecations Added in 3.12.0

Default adapter usage

until: 4.0.0
id: ember-data:default-adapter

Deprecates both store.defaultAdapter (which defaults to -json-api) and the -json-api adapter fallback behavior

Previously, applications could define the store.adapter property which would be used by defaultAdapter and adapterFor as a fallback for when an adapter was not found by an exact name match.

RFC 522 Deprecated specifying and using this property in favor of an explicit application adapter fallback.

If you were not setting this value previously, the following should be sufficient to resolve this deprecation:

create the file app/adapters/application.js with the following:

    export { default } from '@ember-data/adapter/json-api';

If you were setting the adapter property previously to <adapter-name>, create the file app/adapters/application.js with the following:

    export { default } from './<adapter-name>';

More information about custom adapters can be found on the ember.js/guides and in the API DOCs

Default serializers usage

until: 4.0.0
id: ember-data:default-serializers

Default serializer deprecations

Deprecate adapter.defaultSerializer fallback

Moving forward, every app or addon that uses Ember Data must have a serializer explicitly defined.

Previously, if no application or model-type-specific serializer was specified, the store would attempt to look up a serializer via the defaultSerializer property on the type's adapter. This behavior is deprecated in favor of explicitly defining a model-type-specific serializer or application serializer.

You may be relying on the defaultSerializer property set by the Adapter, RESTAdapter or JSONAPIAdapter classes. These classes specified the following defaultSerializer

  • Adapter: -default (@ember-data/serializer/json)
  • RESTAdapter: -rest (@ember-data/serializer/rest)
  • JSONAPIAdapter: -json-api (@ember-data/serializer/json-api)

Clearing these deprecations

If all the adapters in your app are the same kind (such as JSONAPI, REST, or JSON), you should create an application serializer to match.

For example, if you use only JSONAPI adapters, creating the following application serializer will resolve the deprecation:

import DS from 'ember-data';

export default DS.JSONAPISerializer.extend({
  /*custom code*/
});

If your app uses different adapter types for different models, you should make one serializer for each model type. For example, if a certain model uses the RESTAdapter, create an app/serializers/user.js file with the following:

import RESTSerializer from '@ember-data/serializer/rest';

export default RESTSerializer.extend({
  /*custom code*/
});

More information about custom serializers can be found in the Serializer API Docs or in the official guides.

Evented Api Usage

until: 4.0.0
id: ember-data:evented-api-usage

As described in 'RFC 0329' -

Ember.Evented functionality on DS.Model, DS.ManyArray, DS.Errors, DS.RecordArray, and DS.PromiseManyArray will be deprecated and eventually removed in a future release. This includes the following methods from the Ember.Evented class: has, off, on, one, and trigger.

Any code that relies on these objects using the Evented API should be removed. A few scenarios are outlined below.

Derived State

before

class User extends Model {
  @attr() username;

  @on('becameValid', 'becameInvalid')
  updateUsernameAvailability() {
    this.usernameIsAvailable = this.isValid || !this.errors.has('name');
  }
}

after

class User extends Model {
  @attr() username;
  @computed('isValid')
  get usernameIsAvailable() {
    return this.isValid || !this.errors.has('name');
  }
}

Side-effects Driven by User App Code

before

class User extends Model {
  @service() tracking;
  @attr() username;

  @on('didDelete')
  trackDeletion() {
     this.tracking.registerDeletion(this);
  }
}

after

userRecord.deleteRecord();
tracking.registerDeletion(userRecord);

Side-effects Driven by Addon Extensions

Addons that were using these events for managing record state tracking and buffering should consider migrating to providing a custom RecordData implementation.

Record Lifecycle Event Methods

until: 4.0.0
id: ember-data:record-lifecycle-event-methods

Deprecating Record Lifecycle Event Methods

As described in 'RFC 0329' -

...the following lifecycle methods on DS.Model will also be deprecated: becameError, becameInvalid, didCreate, didDelete, didLoad, didUpdate, ready, rolledBack.

When a model is instantiated for the first time with any of these methods a deprecation warning will be logged notifiying the user that this method will be deprecated and the user should use an computed or overide the model's init method instead.

The work of lifecycle events can be achieved with a computed property on a relevant property or kick off additional work when performing the operation.

Some Examples of CP Alternatives:

Other workarounds can be done at the time of interacting with the model. For example, the following could be an alternative to using the didLoad event.

store.findRecord('model', 1).then(function(model) {
  performModelLoadedTask(model);
});

Record toJSON usage

until: 4.0.0
id: ember-data:model.toJSON

Deprecates the built in record.toJSON

Previously users could use record.toJSON to get a simple JSON serialization of a record instance by either calling the method directly or using JSON.stringify(record).

This method used the now deprecated -json serializer to create this JSON representation of the record instead of the user supplied serializer. In addition to the surprising use of a different serializer, this creates an unnecessary dependency on the JSONSerializer for applications that may not otherwise have imported and uses this serializer.

We have deprecated EmberData's own implementation of this method in favor of users implementing their own (or refactoring away).

To clear this deprecation users may call record.serialize() or implement their own toJSON instead. The simplest 1:1 refactor is to import a serializer and define a toJSON method that returns the serialized data from the model, but users may want to consider implementing a custom "serialize" method that outputs relevant data.

An example of the simple refactor is below:

before
  //app/models/post.js
  import Model from '@ember-data/model';

  export default class Post extends Model {};

  //other app code
  const record = store.peekRecord('post');
  // users the default serializer, will have a deprecation warning
  const output = record.toJSON();
after
  //app/models/post.js
  import Model from '@ember-data/model';
  import { JSONAPISerializer } from '@ember-data/serializers';

  export default class Post extends Model {
    toJSON(options) {
      /* Create a JSON object with relevant data by either:
          - iterating the attributes / relationships of the record into a POJO
          - calling this.serialize and then munge output into the desired shape
      */
    }
  };

  //other app code
  const record = store.peekRecord('post');
  // users the default serializer
  const output = record.toJSON();