Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: support full range of json:api for references, update docs #9159

Merged
merged 4 commits into from
Dec 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 60 additions & 79 deletions packages/model/src/-private/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ function computeOnce(target, propertyName, desc) {
}
```

Models are used both to define the static schema for a
particular resource type as well as the class to instantiate
to present that data from cache.

@class Model
@public
@extends Ember.EmberObject
Expand Down Expand Up @@ -863,60 +867,46 @@ class Model extends EmberObject {
/**
Get the reference for the specified belongsTo relationship.

Example
For instance, given the following model

```app/models/blog.js
```app/models/blog-post.js
import Model, { belongsTo } from '@ember-data/model';

export default class BlogModel extends Model {
@belongsTo('user', { async: true, inverse: null }) user;
export default class BlogPost extends Model {
@belongsTo('user', { async: true, inverse: null }) author;
}
```

```javascript
let blog = store.push({
data: {
type: 'blog',
id: 1,
relationships: {
user: {
data: { type: 'user', id: 1 }
}
}
}
});
let userRef = blog.belongsTo('user');
Then the reference for the author relationship would be
retrieved from a record instance like so:

// check if the user relationship is loaded
let isLoaded = userRef.value() !== null;
```js
blogPost.belongsTo('author');
```

// get the record of the reference (null if not yet available)
let user = userRef.value();
A `BelongsToReference` is a low-level API that allows access
and manipulation of a belongsTo relationship.

// get the identifier of the reference
if (userRef.remoteType() === "id") {
let id = userRef.id();
} else if (userRef.remoteType() === "link") {
let link = userRef.link();
}
It is especially useful when you're dealing with `async` relationships
as it allows synchronous access to the relationship data if loaded, as
well as APIs for loading, reloading the data or accessing available
information without triggering a load.

// load user (via store.findRecord or store.findBelongsTo)
userRef.load().then(...)
It may also be useful when using `sync` relationships that need to be
loaded/reloaded with more precise timing than marking the
relationship as `async` and relying on autofetch would have allowed.

// or trigger a reload
userRef.reload().then(...)
However,keep in mind that marking a relationship as `async: false` will introduce
bugs into your application if the data is not always guaranteed to be available
by the time the relationship is accessed. Ergo, it is recommended when using this
approach to utilize `links` for unloaded relationship state instead of identifiers.

// provide data for reference
userRef.push({
type: 'user',
id: 1,
attributes: {
username: "@user"
}
}).then(function(user) {
userRef.value() === user;
});
```
Reference APIs are entangled with the relationship's underlying state,
thus any getters or cached properties that utilize these will properly
invalidate if the relationship state changes.

References are "stable", meaning that multiple calls to retrieve the reference
for a given relationship will always return the same HasManyReference.

@method belongsTo
@public
Expand All @@ -928,55 +918,46 @@ class Model extends EmberObject {
/**
Get the reference for the specified hasMany relationship.

Example
For instance, given the following model

```app/models/blog.js
```app/models/blog-post.js
import Model, { hasMany } from '@ember-data/model';

export default class BlogModel extends Model {
export default class BlogPost extends Model {
@hasMany('comment', { async: true, inverse: null }) comments;
}
```

let blog = store.push({
data: {
type: 'blog',
id: 1,
relationships: {
comments: {
data: [
{ type: 'comment', id: 1 },
{ type: 'comment', id: 2 }
]
}
}
}
});
let commentsRef = blog.hasMany('comments');
Then the reference for the comments relationship would be
retrieved from a record instance like so:

// check if the comments are loaded already
let isLoaded = commentsRef.value() !== null;
```js
blogPost.hasMany('comments');
```

// get the records of the reference (null if not yet available)
let comments = commentsRef.value();
A `HasManyReference` is a low-level API that allows access
and manipulation of a hasMany relationship.

// get the identifier of the reference
if (commentsRef.remoteType() === "ids") {
let ids = commentsRef.ids();
} else if (commentsRef.remoteType() === "link") {
let link = commentsRef.link();
}
It is especially useful when you are dealing with `async` relationships
as it allows synchronous access to the relationship data if loaded, as
well as APIs for loading, reloading the data or accessing available
information without triggering a load.

// load comments (via store.findMany or store.findHasMany)
commentsRef.load().then(...)
It may also be useful when using `sync` relationships with `@ember-data/model`
that need to be loaded/reloaded with more precise timing than marking the
relationship as `async` and relying on autofetch would have allowed.

// or trigger a reload
commentsRef.reload().then(...)
However,keep in mind that marking a relationship as `async: false` will introduce
bugs into your application if the data is not always guaranteed to be available
by the time the relationship is accessed. Ergo, it is recommended when using this
approach to utilize `links` for unloaded relationship state instead of identifiers.

// provide data for reference
commentsRef.push([{ type: 'comment', id: 1 }, { type: 'comment', id: 2 }]).then(function(comments) {
commentsRef.value() === comments;
});
```
Reference APIs are entangled with the relationship's underlying state,
thus any getters or cached properties that utilize these will properly
invalidate if the relationship state changes.

References are "stable", meaning that multiple calls to retrieve the reference
for a given relationship will always return the same HasManyReference.

@method hasMany
@public
Expand Down
Loading
Loading