When eagerly loading relations through a mapper, the opts
argument is passed down to the loaded relations. This breaks the api in my case. For instance:
storyMapper.findAll({ title: 'foobar' }, { with: ['user'] });
This results in two requests:
GET /stories?title=foobar
GET /users?title=foobar
I might be missing something, but I would expect the defined relations to be used so that the story is loaded first, it's userId
field read, and the second query be something like
GET /users/<the id>
Or at least
GET /users?where=<id in <the id>>
So my question is; can i change the behavior of this or do I need to use loadRelations
on each story after it has loaded?
Code samples:
// user schema
import { Schema } from 'js-data';
export const user = new Schema({
$schema: 'http://json-schema.org/draft-04/schema#',
title: 'User',
description: 'Schema for User records',
type: 'object',
properties: {
_id: { type: 'string' },
username: { type: 'string' },
email: { type: 'string' },
password: { type: 'string' },
},
required: ['username', 'email', 'password'],
});
// story schema
import { Schema } from 'js-data';
export const story = new Schema({
$schema: 'http://json-schema.org/draft-04/schema#',
title: 'Story',
description: 'Schema for Story records',
type: 'object',
properties: {
_id: { type: 'string' },
title: { type: 'string', default: '' },
userId: { type: ['string', 'null'] },
username: { type: ['string', 'null'] },
},
required: ['title'],
});
// user mapper
this.store.defineMapper('user', {
mapperClass: ObservableMapper,
recordClass: User,
endpoint: 'users',
idAttribute: '_id',
schema: schemas.user,
relations: relations.user,
})
// story mapper
this.store.defineMapper('story', {
mapperClass: ObservableMapper,
recordClass: Story,
endpoint: 'storys',
idAttribute: '_id',
schema: schemas.story,
relations: relations.story,
})
// user relations
export const user = {
hasMany: {
world: {
foreignKey: 'userId',
localField: 'worlds',
},
},
};
// story relations
export const world = {
belongsTo: {
user: {
foreignKey: 'userId',
localField: 'user',
},
},
};
Sample data returned from GET /stories?title=foobar
:
{
"_id": "546e53dcedee82d542000003",
"userId": "526e8617964fd22d2b000001",
"username": "Someone",
"title": "Lorem Ipsum"
}
You're missing the other side of the User-Story relation:
Now, when you actually make the request you have two options:
Option 1 - Multiple requests
This requires that your server understands the "where" querystring parameter:
Here's a plunker that demonstrates: https://plnkr.co/edit/UCFJNg?p=preview
The plunker example makes two requests:
GET /stories?title=foobar
GET /users?title=foobar&where={"_id":{"in":[123,234]}}
Option 2 - A single request
This requires that your server understands the "with" querystring parameter:
Here's a plunker that demonstrates: https://plnkr.co/edit/M6quP4?p=preview
The plunker example makes just one request, and expects the users to be embedded within the stories in the server's response:
GET /stories?with=user&title=foobar
Note
This is a quirk of the HTTP adapter. For all other adapters, using the
with
option works as you'd expect, and you don't have to mess with theparams
option.