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

Update finding Record section in ember-data guides to teach request service #2030

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
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
94 changes: 49 additions & 45 deletions guides/release/models/finding-records.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,36 @@ The EmberData store provides an interface for retrieving records of a single typ

### Retrieving a Single Record

Use [`store.findRecord()`](https://api.emberjs.com/ember-data/release/classes/Store/methods/findRecord?anchor=findRecord) to retrieve a record by its type and ID.
This will return a promise that fulfills with the requested record:
Use [`findRecord()`](https://api.emberjs.com/ember-data/5.3/functions/@ember-data%2Fjson-api%2Frequest/findRecord) to retrieve a record by its type and ID.
This will return a single `record` or a `array` depends upon the response from server:

```javascript
// GET /blog-posts/1
this.store.findRecord('blog-post', 1) // => GET /blog-posts/1
.then(function(blogPost) {
// Do something with `blogPost`
});
// GET /blog-post/1
import { service } from '@ember/service';
import { findRecord } from '@ember-data/json-api/request';

// somewhere in the app
const result = await store.request(findRecord('blog-post', '1'));
const blogPost = result.content.data;
```

Use [`store.peekRecord()`](https://api.emberjs.com/ember-data/release/classes/Store/methods/peekRecord?anchor=peekRecord) to retrieve a record by its type and ID, without making a network request.
This will return the record only if it is already present in the store:

```javascript
let blogPost = this.store.peekRecord('blog-post', 1); // => no network request
let blogPost = this.store.peekRecord('blog-post', '1'); // => no network request
```

### Retrieving Multiple Records

Use [`store.findAll()`](https://api.emberjs.com/ember-data/release/classes/Store/methods/findAll?anchor=findAll) to retrieve all of the records for a given type:
Use [`query()`](https://api.emberjs.com/ember-data/5.3/functions/@ember-data%2Fjson-api%2Frequest/query) to retrieve all of the records for a given type:

```javascript
// GET /blog-posts
this.store.findAll('blog-post') // => GET /blog-posts
.then(function(blogPosts) {
// Do something with `blogPosts`
});
import { query } from '@ember-data/json-api/request';

const result = await store.request(query('blog-post'));
const blogPosts = result.content.data;
```

Use [`store.peekAll()`](https://api.emberjs.com/ember-data/release/classes/Store/methods/peekAll?anchor=peekAll) to retrieve all of the records for a given type that are already loaded into the store, without making a network request:
Expand All @@ -38,7 +40,7 @@ Use [`store.peekAll()`](https://api.emberjs.com/ember-data/release/classes/Store
let blogPosts = this.store.peekAll('blog-post'); // => no network request
```

`store.findAll()` returns a `PromiseArray` that fulfills to a `RecordArray` and `store.peekAll` directly returns a `RecordArray`.
`findRecord()` returns a `response` which has the record and `store.peekAll` directly returns a `RecordArray`.

It's important to note that `RecordArray` is not a JavaScript array, it's an object that implements [`MutableArray`](https://api.emberjs.com/ember/release/classes/MutableArray).
This is important because, for example, if you want to retrieve records by index,
Expand All @@ -47,28 +49,29 @@ the `[]` notation will not work--you'll have to use `objectAt(index)` instead.
### Querying for Multiple Records

EmberData provides the ability to query for records that meet certain criteria.
Calling [`store.query()`](https://api.emberjs.com/ember-data/release/classes/Store/methods/query?anchor=query) will make a `GET` request with the passed object serialized as query params.
This method returns a `PromiseArray` in the same way as `findAll`.
Calling [`query()`](https://api.emberjs.com/ember-data/5.3/functions/@ember-data%2Fjson-api%2Frequest/query) will make a `GET` request with the passed object serialized as query params.
This method returns a respone from the server in the same way as `findRecord`.
MehulKChaudhari marked this conversation as resolved.
Show resolved Hide resolved

For example, we could search for all `person` models who have the name of
`Peter`:

```javascript
// GET to /persons?filter[name]=Peter
this.store.query('person', {
import { query } from '@ember-data/json-api/request';

const result = await store.request(query('person', {
filter: {
name: 'Peter'
}
}).then(function(peters) {
// Do something with `peters`
});
}));
const person = result.content.data;
```

### Querying for A Single Record

If you are using an adapter that supports server requests capable of returning a single model object,
EmberData provides a convenience method [`store.queryRecord()`](https://api.emberjs.com/ember-data/release/classes/Store/methods/queryRecord?anchor=queryRecord) that will return a promise that resolves with that single record.
The request is made via a method `queryRecord()` defined by the adapter.
If you are using an builder that supports server requests capable of returning a single model object,
MehulKChaudhari marked this conversation as resolved.
Show resolved Hide resolved
EmberData provides a convenience method [`findRecord()`](https://api.emberjs.com/ember-data/5.3/functions/@ember-data%2Fjson-api%2Frequest/findRecord) that will return a record.
The request is made via a method `findRecord()` defined by the builders.

For example, if your server API provides an endpoint for the currently logged in user:

Expand All @@ -82,43 +85,44 @@ For example, if your server API provides an endpoint for the currently logged in
}
```

And if the adapter for the `User` model defines a `queryRecord()` method that targets that endpoint:

```javascript {data-filename=app/adapters/user.js}
import Adapter from '@ember-data/adapter';
import fetch from 'fetch';

export default class UserAdapter extends Adapter {
queryRecord(store, type, query) {
return fetch('/api/current_user');
}
And if the builders for the `User` model defines a `queryData()` method that targets that endpoint:

```javascript {data-filename=app/builders/user.js}
export function queryData() {
return {
url: `/api/current_user`,
MehulKChaudhari marked this conversation as resolved.
Show resolved Hide resolved
method: 'GET',
headers: {
'Content-Type': 'application/json'
},
}
}
```

Then, calling [`store.queryRecord()`](https://api.emberjs.com/ember-data/release/classes/Store/methods/queryRecord?anchor=queryRecord) will retrieve that object from the server:
Then, calling `queryData()` will retrieve that object from the server:

```javascript
store.queryRecord('user', {}).then(function(user) {
let username = user.get('username');
console.log(`Currently logged in as ${username}`);
});
import { queryData } from './builders';

const user = await requestManager.request(queryData());
let username = user.get('username');

console.log(`Currently logged in as ${username}`);
```

As in the case of `store.query()`, a query object can also be passed to `store.queryRecord()` and is available for the adapter's `queryRecord()` to use to qualify the request.
However the adapter must return a single model object, not an array containing one element,
As in the case of `query()`, a query object can also be passed to `query()` and is available for the builder's `query()` to use to qualify the request.
However the builder must return a single model object, not an array containing one element,
otherwise EmberData will throw an exception.

Note that Ember's default [JSON:API adapter](https://api.emberjs.com/ember-data/release/classes/JSONAPIAdapter) does not provide the functionality needed to support `queryRecord()` directly as it relies on REST request definitions that return result data in the form of an array.

If your server API or your adapter only provides array responses but you wish to retrieve just a single record, you can alternatively use the `query()` method as follows:
If your server API or your builder only provides array responses but you wish to retrieve just a single record, you can alternatively use the `query()` method as follows:

```javascript
// GET to /users?filter[email]=tomster@example.com
tom = store.query('user', {
tom = requestManager.request(queryData('user', {
filter: {
email: 'tomster@example.com'
}
}).then(function(users) {
})).then(function(users) {
return users[0]; // the first object
});
```
Expand Down