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/adapters/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

Previously, if no application or type-specific serializer was specified, the store would attempt to lookup a serializer via the defaultSerializer property on the type's adapter. This behavior is deprecated in favor of explicitly defining a 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)

If a per-type adapter exists for the modelName triggering this deprecation, the easiest resolution is to add a per-type serializer.

If the application adapter is triggering this deprecation, then an application serializer should be added.

More information on adding these serializers can be found in "clearing these deprecations" below.

-default serializer fallback in store.serializerFor

Previously, when no type-specific serializer, application serializer, or adapter defaultSerializer had been defined by the app, the -default serializer would be used which defaulted to the JSONSerializer. This behavior is deprecated in favor of explicitly defining an application or type-specific serializer as described below.

clearing these deprecations

More information about custom serializers can be found in the Serializer API Docs or on the ember.js/guides

If a specific model type requires custom serialization, a type-specific serializer can be created. A single application serializer can be used a for any model types not requiring custom serialization. To define a type-specific serializer, create an app/serializers/[type].js with the following:

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

    export default class UserSerializer extends RESTSerializer {
      /*custom code*/
    }

Defining a serializer for the entire application can be done by adding the file app/serializers/application.js with the following:

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

Evented Api Usage

until: 4.0.0
id: 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: 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: record.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();