diff --git a/packages/model/addon/-private/attr.js b/packages/model/addon/-private/attr.js
index 30e00be13fb..19a191c186f 100644
--- a/packages/model/addon/-private/attr.js
+++ b/packages/model/addon/-private/attr.js
@@ -49,11 +49,11 @@ function hasValue(internalModel, key) {
```app/models/user.js
import Model, { attr } from '@ember-data/model';
- export default Model.extend({
- username: attr('string'),
- email: attr('string'),
- verified: attr('boolean', { defaultValue: false })
- });
+ export default class UserModel extends Model {
+ @attr('string') username;
+ @attr('string') email;
+ @attr('boolean', { defaultValue: false }) verified;
+ }
```
Default value can also be a function. This is useful it you want to return
@@ -62,15 +62,17 @@ function hasValue(internalModel, key) {
```app/models/user.js
import Model, { attr } from '@ember-data/model';
- export default Model.extend({
- username: attr('string'),
- email: attr('string'),
- settings: attr({
+ export default class UserModel extends Model {
+ @attr('string') username;
+ @attr('string') email;
+
+ @attr({
defaultValue() {
return {};
}
})
- });
+ settings;
+ }
```
The `options` hash is passed as second argument to a transforms'
@@ -80,11 +82,12 @@ function hasValue(internalModel, key) {
```app/models/post.js
import Model, { attr } from '@ember-data/model';
- export default Model.extend({
- text: attr('text', {
+ export default class PostModel extends Model {
+ @attr('text', {
uppercase: true
})
- });
+ text;
+ }
```
```app/transforms/text.js
diff --git a/packages/model/addon/-private/belongs-to.js b/packages/model/addon/-private/belongs-to.js
index 0a45faa3f5f..8e780af054f 100644
--- a/packages/model/addon/-private/belongs-to.js
+++ b/packages/model/addon/-private/belongs-to.js
@@ -30,17 +30,17 @@ import { computedMacroWithOptionalParams } from './util';
```app/models/user.js
import Model, { belongsTo } from '@ember-data/model';
- export default Model.extend({
- profile: belongsTo('profile')
- });
+ export default class UserModel extends Model {
+ @belongsTo('profile') profile;
+ }
```
```app/models/profile.js
import Model, { belongsTo } from '@ember-data/model';
- export default Model.extend({
- user: belongsTo('user')
- });
+ export default class ProfileModel extends Model {
+ @belongsTo('user') user;
+ }
```
#### One-To-Many
@@ -50,17 +50,17 @@ import { computedMacroWithOptionalParams } from './util';
```app/models/post.js
import Model, { hasMany } from '@ember-data/model';
- export default Model.extend({
- comments: hasMany('comment')
- });
+ export default class PostModel extends Model {
+ @hasMany('comment') comments;
+ }
```
```app/models/comment.js
import Model, { belongsTo } from '@ember-data/model';
- export default Model.extend({
- post: belongsTo('post')
- });
+ export default class CommentModel extends Model {
+ @belongsTo('post') post;
+ }
```
You can avoid passing a string as the first parameter. In that case Ember Data
@@ -69,9 +69,9 @@ import { computedMacroWithOptionalParams } from './util';
```app/models/comment.js
import Model, { belongsTo } from '@ember-data/model';
- export default Model.extend({
- post: belongsTo()
- });
+ export default class CommentModel extends Model {
+ @belongsTo post;
+ }
```
will lookup for a Post type.
@@ -85,11 +85,12 @@ import { computedMacroWithOptionalParams } from './util';
```app/models/comment.js
import Model, { belongsTo } from '@ember-data/model';
- export default Model.extend({
- post: belongsTo('post', {
+ export default class CommentModel extends Model {
+ @belongsTo('post', {
async: false
})
- });
+ post;
+ }
```
In contrast to async relationship, accessing a sync relationship
diff --git a/packages/model/addon/-private/errors.js b/packages/model/addon/-private/errors.js
index d4d618f7dc9..0b3eeb0354f 100644
--- a/packages/model/addon/-private/errors.js
+++ b/packages/model/addon/-private/errors.js
@@ -22,10 +22,10 @@ import { DeprecatedEvented } from '@ember-data/store/-private';
```app/models/user.js
import Model, { attr } from '@ember-data/model';
- export default Model.extend({
- username: attr('string'),
- email: attr('string')
- });
+ export default class UserModel extends Model {
+ @attr('string') username;
+ @attr('string') email;
+ }
```
And you attempted to save a record that did not validate on the backend:
@@ -53,15 +53,15 @@ import { DeprecatedEvented } from '@ember-data/store/-private';
- `attribute` The name of the property associated with this error message
```handlebars
-
- {{#each model.errors.username as |error|}}
+
+ {{#each @model.errors.username as |error|}}
{{error.message}}
{{/each}}
-
- {{#each model.errors.email as |error|}}
+
+ {{#each @model.errors.email as |error|}}
{{error.message}}
@@ -72,7 +72,7 @@ import { DeprecatedEvented } from '@ember-data/store/-private';
object to get an array of all the error strings.
```handlebars
- {{#each model.errors.messages as |message|}}
+ {{#each @model.errors.messages as |message|}}
{{message}}
@@ -148,7 +148,7 @@ export default ArrayProxy.extend(DeprecatedEvented, {
record. This is useful for displaying all errors to the user.
```handlebars
- {{#each model.errors.messages as |message|}}
+ {{#each @model.errors.messages as |message|}}
{{message}}
@@ -425,19 +425,19 @@ export default ArrayProxy.extend(DeprecatedEvented, {
/**
Checks if there are error messages for the given attribute.
- ```app/routes/user/edit.js
- import Route from '@ember/routing/route';
+ ```app/controllers/user/edit.js
+ import Controller from '@ember/controller';
+ import { action } from '@ember/object';
- export default Route.extend({
- actions: {
- save: function(user) {
- if (user.get('errors').has('email')) {
- return alert('Please update your email before attempting to save.');
- }
- user.save();
+ export default class UserEditController extends Controller {
+ @action
+ save(user) {
+ if (user.get('errors').has('email')) {
+ return alert('Please update your email before attempting to save.');
}
+ user.save();
}
- });
+ }
```
@method has
diff --git a/packages/model/addon/-private/has-many.js b/packages/model/addon/-private/has-many.js
index 366144a05c4..9d05e740d3b 100644
--- a/packages/model/addon/-private/has-many.js
+++ b/packages/model/addon/-private/has-many.js
@@ -26,18 +26,18 @@ import { computedMacroWithOptionalParams } from './util';
```app/models/post.js
import Model, { hasMany } from '@ember-data/model';
-
- export default Model.extend({
- comments: hasMany('comment')
- });
+
+ export default class PostModel extends Model {
+ @hasMany('comment') comments;
+ }
```
```app/models/comment.js
import Model, { belongsTo } from '@ember-data/model';
-
- export default Model.extend({
- post: belongsTo('post')
- });
+
+ export default class CommentModel extends Model {
+ @belongsTo('post') post;
+ }
```
#### Many-To-Many
@@ -47,17 +47,17 @@ import { computedMacroWithOptionalParams } from './util';
```app/models/post.js
import Model, { hasMany } from '@ember-data/model';
- export default Model.extend({
- tags: hasMany('tag')
- });
+ export default class PostModel extends Model {
+ @hasMany('tag') tags;
+ }
```
```app/models/tag.js
import Model, { hasMany } from '@ember-data/model';
- export default Model.extend({
- posts: hasMany('post')
- });
+ export default class TagModel extends Model {
+ @hasMany('post') posts;
+ }
```
You can avoid passing a string as the first parameter. In that case Ember Data
@@ -66,9 +66,9 @@ import { computedMacroWithOptionalParams } from './util';
```app/models/post.js
import Model, { hasMany } from '@ember-data/model';
- export default Model.extend({
- tags: hasMany()
- });
+ export default class PostModel extends Model {
+ @hasMany tags;
+ }
```
will lookup for a Tag type.
@@ -88,22 +88,24 @@ import { computedMacroWithOptionalParams } from './util';
```app/models/comment.js
import Model, { belongsTo } from '@ember-data/model';
- export default Model.extend({
- onePost: belongsTo('post'),
- twoPost: belongsTo('post'),
- redPost: belongsTo('post'),
- bluePost: belongsTo('post')
- });
+ export default class CommentModel extends Model {
+ @belongsTo('post') onePost;
+ @belongsTo('post') twoPost
+ @belongsTo('post') redPost;
+ @belongsTo('post') bluePost;
+ }
```
```app/models/post.js
- import Model, { hasMany } from '@ember-data/model';
+ import Model from '@ember-data/model';
+ import { hasMany } from '@ember-decorators/data';
- export default Model.extend({
- comments: hasMany('comment', {
+ export default class PostModel extends Model {
+ @hasMany('comment', {
inverse: 'redPost'
})
- });
+ comments;
+ }
```
You can also specify an inverse on a `belongsTo`, which works how
@@ -118,11 +120,12 @@ import { computedMacroWithOptionalParams } from './util';
```app/models/post.js
import Model, { hasMany } from '@ember-data/model';
- export default Model.extend({
- comments: hasMany('comment', {
+ export default class PostModel extends Model {
+ @hasMany('comment', {
async: false
})
- });
+ comments;
+ }
```
In contrast to async relationship, accessing a sync relationship
diff --git a/packages/model/addon/-private/model.js b/packages/model/addon/-private/model.js
index 938254133d2..91558f4e3d0 100644
--- a/packages/model/addon/-private/model.js
+++ b/packages/model/addon/-private/model.js
@@ -512,18 +512,18 @@ const Model = EmberObject.extend(DeprecatedEvented, {
});
```
- The `errors` property us useful for displaying error messages to
+ The `errors` property is useful for displaying error messages to
the user.
```handlebars
-
- {{#each model.errors.username as |error|}}
+
+ {{#each @model.errors.username as |error|}}
{{error.message}}
{{/each}}
-
- {{#each model.errors.email as |error|}}
+
+ {{#each @model.errors.email as |error|}}
{{error.message}}
@@ -535,7 +535,7 @@ const Model = EmberObject.extend(DeprecatedEvented, {
object to get an array of all the error strings.
```handlebars
- {{#each model.errors.messages as |message|}}
+ {{#each @model.errors.messages as |message|}}
{{message}}
@@ -706,22 +706,26 @@ const Model = EmberObject.extend(DeprecatedEvented, {
Example
- ```app/routes/model/delete.js
- import Route from '@ember/routing/route';
-
- export default Route.extend({
- actions: {
- softDelete() {
- this.get('controller.model').deleteRecord();
- },
- confirm() {
- this.get('controller.model').save();
- },
- undo() {
- this.get('controller.model').rollbackAttributes();
- }
+ ```app/controllers/model/delete.js
+ import Controller from '@ember/controller';
+ import { action } from '@ember/object';
+
+ export default class ModelDeleteController extends Controller {
+ @action
+ softDelete() {
+ this.model.deleteRecord();
}
- });
+
+ @action
+ confirm() {
+ this.model.save();
+ }
+
+ @action
+ undo() {
+ this.model.rollbackAttributes();
+ }
+ }
```
@method deleteRecord
@@ -735,18 +739,18 @@ const Model = EmberObject.extend(DeprecatedEvented, {
Example
- ```app/routes/model/delete.js
- import Route from '@ember/routing/route';
+ ```app/controllers/model/delete.js
+ import Controller from '@ember/controller';
+ import { action } from '@ember/object';
- export default Route.extend({
- actions: {
- delete() {
- this.get('controller.model').destroyRecord().then(function() {
- controller.transitionToRoute('model.index');
- });
- }
- }
- });
+ export default class ModelDeleteController extends Controller {
+ @action
+ delete() {
+ this.model.destroyRecord().then(function() {
+ this.transitionToRoute('model.index');
+ });
+ }
+ }
```
If you pass an object on the `adapterOptions` property of the options
@@ -759,14 +763,14 @@ const Model = EmberObject.extend(DeprecatedEvented, {
```app/adapters/post.js
import MyCustomAdapter from './custom-adapter';
- export default MyCustomAdapter.extend({
+ export default class PostAdapter extends MyCustomAdapter {
deleteRecord(store, type, snapshot) {
if (snapshot.adapterOptions.subscribe) {
// ...
}
// ...
}
- });
+ }
```
@method destroyRecord
@@ -822,12 +826,13 @@ const Model = EmberObject.extend(DeprecatedEvented, {
```app/models/mascot.js
import Model, { attr } from '@ember-data/model';
- export default Model.extend({
- name: attr('string'),
- isAdmin: attr('boolean', {
+ export default class MascotModel extends Model {
+ @attr('string') name;
+ @attr('boolean', {
defaultValue: false
})
- });
+ isAdmin;
+ }
```
```javascript
@@ -924,14 +929,14 @@ const Model = EmberObject.extend(DeprecatedEvented, {
```app/adapters/post.js
import MyCustomAdapter from './custom-adapter';
- export default MyCustomAdapter.extend({
+ export default class PostAdapter extends MyCustomAdapter {
updateRecord(store, type, snapshot) {
if (snapshot.adapterOptions.subscribe) {
// ...
}
// ...
}
- });
+ }
```
@method save
@@ -952,18 +957,18 @@ const Model = EmberObject.extend(DeprecatedEvented, {
Example
- ```app/routes/model/view.js
- import Route from '@ember/routing/route';
+ ```app/controllers/model/view.js
+ import Controller from '@ember/controller';
+ import { action } from '@ember/object';
- export default Route.extend({
- actions: {
- reload() {
- this.controller.get('model').reload().then(function(model) {
- // do something with the reloaded model
- });
- }
+ export default class ViewController extends Controller {
+ @action
+ reload() {
+ this.model.reload().then(function(model) {
+ // do something with the reloaded model
+ });
}
- });
+ }
```
@method reload
@@ -1002,9 +1007,9 @@ const Model = EmberObject.extend(DeprecatedEvented, {
```app/models/blog.js
import Model, { belongsTo } from '@ember-data/model';
- export default Model.extend({
- user: belongsTo({ async: true })
- });
+ export default class BlogModel extends Model {
+ @belongsTo({ async: true }) user;
+ }
```
```javascript
@@ -1069,9 +1074,9 @@ const Model = EmberObject.extend(DeprecatedEvented, {
```app/models/blog.js
import Model, { hasMany } from '@ember-data/model';
- export default Model.extend({
- comments: hasMany({ async: true })
- });
+ export default class BlogModel extends Model {
+ @hasMany({ async: true }) comments;
+ }
let blog = store.push({
data: {
@@ -1220,8 +1225,8 @@ const Model = EmberObject.extend(DeprecatedEvented, {
```app/serializers/application.js
import JSONSerializer from '@ember-data/serializer/json';
- export default JSONSerializer.extend({
- serialize: function(record, options) {
+ export default class ApplicationSerializer extends JSONSerializer {
+ serialize(record, options) {
let json = {};
record.eachRelationship(function(name, descriptor) {
@@ -1233,7 +1238,7 @@ const Model = EmberObject.extend(DeprecatedEvented, {
return json;
}
- });
+ }
```
@method eachRelationship
@@ -1556,9 +1561,9 @@ Model.reopenClass({
```app/models/post.js
import Model, { hasMany } from '@ember-data/model';
- export default Model.extend({
- comments: hasMany('comment')
- });
+ export default class PostModel extends Model {
+ @hasMany('comment') comments;
+ }
```
Calling `store.modelFor('post').typeForRelationship('comments', store)` will return `Comment`.
@@ -1586,17 +1591,18 @@ Model.reopenClass({
```app/models/post.js
import Model, { hasMany } from '@ember-data/model';
- export default Model.extend({
- comments: hasMany('message')
- });
+ export default class PostModel extends Model {
+ @hasMany('message') comments;
+ }
```
```app/models/message.js
- import Model, { belongsTo } from '@ember-data/model';
+ import Model from '@ember-data/model';
+ import { belongsTo } from '@ember-decorators/data';
- export default Model.extend({
- owner: belongsTo('post')
- });
+ export default class MessageModel extends Model {
+ @belongsTo('post') owner;
+ }
```
``` js
@@ -1734,23 +1740,23 @@ Model.reopenClass({
```app/models/blog.js
import Model, { belongsTo, hasMany } from '@ember-data/model';
- export default Model.extend({
- users: hasMany('user'),
- owner: belongsTo('user'),
- posts: hasMany('post')
- });
+ export default class BlogModel extends Model {
+ @hasMany('user') users;
+ @belongsTo('user') owner;
+ @hasMany('post') posts;
+ }
```
This computed property would return a map describing these
relationships, like this:
```javascript
- import Ember from 'ember';
+ import { get } from '@ember/object';
import Blog from 'app/models/blog';
import User from 'app/models/user';
import Post from 'app/models/post';
- let relationships = Ember.get(Blog, 'relationships');
+ let relationships = get(Blog, 'relationships');
relationships.get('user');
//=> [ { name: 'users', kind: 'hasMany' },
// { name: 'owner', kind: 'belongsTo' } ]
@@ -1774,21 +1780,21 @@ Model.reopenClass({
```app/models/blog.js
import Model, { belongsTo, hasMany } from '@ember-data/model';
- export default Model.extend({
- users: hasMany('user'),
- owner: belongsTo('user'),
+ export default class BlogModel extends Model {
+ @hasMany('user') users;
+ @belongsTo('user') owner;
- posts: hasMany('post')
- });
+ @hasMany('post') posts;
+ }
```
This property would contain the following:
```javascript
- import Ember from 'ember';
+ import { get } from '@ember/object';
import Blog from 'app/models/blog';
- let relationshipNames = Ember.get(Blog, 'relationshipNames');
+ let relationshipNames = get(Blog, 'relationshipNames');
relationshipNames.hasMany;
//=> ['users', 'posts']
relationshipNames.belongsTo;
@@ -1825,21 +1831,21 @@ Model.reopenClass({
```app/models/blog.js
import Model, { belongsTo, hasMany } from '@ember-data/model';
- export default Model.extend({
- users: hasMany('user'),
- owner: belongsTo('user'),
+ export default class BlogModel extends Model {
+ @hasMany('user') users;
+ @belongsTo('user') owner;
- posts: hasMany('post')
- });
+ @hasMany('post') posts;
+ }
```
This property would contain the following:
```javascript
- import Ember from 'ember';
+ import { get } from '@ember/object';
import Blog from 'app/models/blog';
- let relatedTypes = Ember.get(Blog, 'relatedTypes');
+ let relatedTypes = get(Blog, 'relatedTypes');
//=> [ User, Post ]
```
@@ -1860,21 +1866,21 @@ Model.reopenClass({
```app/models/blog.js
import Model, { belongsTo, hasMany } from '@ember-data/model';
- export default Model.extend({
- users: hasMany('user'),
- owner: belongsTo('user'),
+ export default class BlogModel extends Model {
+ @hasMany('user') users;
+ @belongsTo('user') owner;
- posts: hasMany('post')
- });
+ @hasMany('post') posts;
+ }
```
This property would contain the following:
```javascript
- import Ember from 'ember';
+ import { get } from '@ember/object';
import Blog from 'app/models/blog';
- let relationshipsByName = Ember.get(Blog, 'relationshipsByName');
+ let relationshipsByName = get(Blog, 'relationshipsByName');
relationshipsByName.get('users');
//=> { key: 'users', kind: 'hasMany', type: 'user', options: Object, isRelationship: true }
relationshipsByName.get('owner');
@@ -1900,21 +1906,21 @@ Model.reopenClass({
```app/models/blog.js
import Model, { attr, belongsTo, hasMany } from '@ember-data/model';
- export default Model.extend({
- users: hasMany('user'),
- owner: belongsTo('user'),
+ export default class BlogModel extends Model {
+ @hasMany('user') users;
+ @belongsTo('user') owner;
- posts: hasMany('post'),
+ @hasMany('post') posts;
- title: attr('string')
- });
+ @attr('string') title;
+ }
```
```js
- import Ember from 'ember';
- import Blog from 'app/models/blog';
+ import { get } from '@ember/object';
+ import Blog from 'app/models/blog'
- let fields = Ember.get(Blog, 'fields');
+ let fields = get(Blog, 'fields');
fields.forEach(function(kind, field) {
console.log(field, kind);
});
@@ -2012,18 +2018,18 @@ Model.reopenClass({
```app/models/person.js
import Model, { attr } from '@ember-data/model';
- export default Model.extend({
- firstName: attr('string'),
- lastName: attr('string'),
- birthday: attr('date')
- });
+ export default class PersonModel extends Model {
+ @attr('string') firstName;
+ @attr('string') lastName;
+ @attr('date') birthday;
+ }
```
```javascript
- import Ember from 'ember';
- import Person from 'app/models/person';
+ import { get } from '@ember/object';
+ import Blog from 'app/models/blog'
- let attributes = Ember.get(Person, 'attributes')
+ let attributes = get(Person, 'attributes')
attributes.forEach(function(meta, name) {
console.log(name, meta);
@@ -2070,18 +2076,18 @@ Model.reopenClass({
```app/models/person.js
import Model, { attr } from '@ember-data/model';
- export default Model.extend({
- firstName: attr(),
- lastName: attr('string'),
- birthday: attr('date')
- });
+ export default class PersonModel extends Model {
+ @attr firstName;
+ @attr('string') lastName;
+ @attr('date') birthday;
+ }
```
```javascript
- import Ember from 'ember';
+ import { get } from '@ember/object';
import Person from 'app/models/person';
- let transformedAttributes = Ember.get(Person, 'transformedAttributes')
+ let transformedAttributes = get(Person, 'transformedAttributes')
transformedAttributes.forEach(function(field, type) {
console.log(field, type);
@@ -2131,13 +2137,13 @@ Model.reopenClass({
```javascript
import Model, { attr } from '@ember-data/model';
- let Person = Model.extend({
- firstName: attr('string'),
- lastName: attr('string'),
- birthday: attr('date')
- });
+ class PersonModel extends Model {
+ @attr('string') firstName;
+ @attr('string') lastName;
+ @attr('date') birthday;
+ }
- Person.eachAttribute(function(name, meta) {
+ PersonModel.eachAttribute(function(name, meta) {
console.log(name, meta);
});
diff --git a/packages/model/addon/-private/system/many-array.js b/packages/model/addon/-private/system/many-array.js
index 2af7375b67c..70aa77fcffc 100644
--- a/packages/model/addon/-private/system/many-array.js
+++ b/packages/model/addon/-private/system/many-array.js
@@ -28,17 +28,17 @@ import { _objectIsAlive, DeprecatedEvented, diffArray, PromiseArray, recordDataF
```app/models/post.js
import Model, { hasMany } from '@ember-data/model';
- export default Model.extend({
- comments: hasMany('comment')
- });
+ export default class PostModel extends Model {
+ @hasMany('comment') comments;
+ }
```
```app/models/comment.js
import Model, { belongsTo } from '@ember-data/model';
- export default Model.extend({
- post: belongsTo('post')
- });
+ export default class CommentModel extends Model {
+ @belongsTo('post') post;
+ }
```
If you created a new instance of `Post` and added
diff --git a/packages/model/addon/-private/system/model-for-mixin.ts b/packages/model/addon/-private/system/model-for-mixin.ts
index 901ace21496..f11979f3de6 100644
--- a/packages/model/addon/-private/system/model-for-mixin.ts
+++ b/packages/model/addon/-private/system/model-for-mixin.ts
@@ -3,15 +3,18 @@ import { getOwner } from '@ember/application';
import Model from '../model';
type Store = import('@ember-data/store').default;
-
-/*
+/*
In case someone defined a relationship to a mixin, for example:
```
- let Comment = Model.extend({
- owner: belongsTo('commentable'. { polymorphic: true })
- });
- let Commentable = Ember.Mixin.create({
- comments: hasMany('comment')
+ import Model, { belongsTo, hasMany } from '@ember-data/model';
+ import Mixin from '@ember/object/mixin';
+
+ class CommentModel extends Model {
+ @belongsTo('commentable', { polymorphic: true }) owner;
+ }
+
+ let Commentable = Mixin.create({
+ @hasMany('comment') comments;
});
```
we want to look up a Commentable class which has all the necessary
diff --git a/packages/model/addon/index.ts b/packages/model/addon/index.ts
index a163837e30b..480a8e0628d 100644
--- a/packages/model/addon/index.ts
+++ b/packages/model/addon/index.ts
@@ -18,13 +18,13 @@
```app/models/person.js
import Model, { attr, belongsTo, hasMany } from '@ember-data/model';
- export default Model.extend({
- name: attr(),
+ export default class PersonModel extends Model {
+ @attr name;
- dog: belongsTo('pet', { inverse: 'owners', async: false }),
+ @belongsTo('pet', { inverse: 'owners', async: false }) dog;
- friends: hasMany('person', { inverse: 'friends', async: true }),
- });
+ @hasMany('person', { inverse: 'friends', async: true }) friends;
+ }
```
### modelName convention