Error using params options with DS.find
rgant opened this issue · comments
I haven't really looked into this issue yet. More details to come. However if I run:
DS.find('users', 'me').then(function (myUser) {
console.log('HERE:', myUser);
});
Then I see the request /v3/users/me
and I get the model in the .then
and everything works great.
However if I add a parameters option to the find it doesn't work.
DS.find('users', 'me', {params: {include: 'account'}}).then(function (myUser) {
console.log('THERE:', myUser);
});
I see the request /v3/users/me?include=account
but I don't get the model in the .then
. I appears that the .then
is not called at all as I don't even get the logging message 'THERE:' in my browser's console.
The issue appears to be related to #25. I get the following error when attempting to deserialize the account document:
Error: MISSING: Relationship definition on js-data resource, Name:users, failed to load relationship named: account.Your js-data store configuration does not match your jsonapi data structure(…)
Ok, so the issue is that I defined the users Resource as:
DS.defineResource({
name: 'users',
relations: {
belongsTo: {
accounts: {
localField: 'account',
localKey: 'accountid'
}
}
}
});
If I change that to hasOne it works:
DS.defineResource({
name: 'users',
relations: {
hasOne: {
accounts: {
localField: 'account',
localKey: 'accountid'
}
}
}
});
I think there probably needs to be a good review of the relationships handling code. I'll look at doing that in my branch.
Ok i think the belongsTo
relationship needs some explanation.
JsonApi defines child relationships only. These are represented by hasOne , hasMany
relationships in js-data.
The belongsTo
relationship defines a parent relationship. The User belongs to a parent Organisation for example. This type of relationship is not and should not be represented by JsonApi or any REST service for that matter.
The reason being that a REST document should not change as a side effect of changing some other document. e.g. If we remove a user from an organisation's Users relationship there cannot be any keys, e.g. Parent keys in the child user that need to be updated as well. (This would make your user document non-cacheable)
However when dealing with data on the client it is very useful to be able to access an object's parent. Business rules often require this and it is commonly implemented on server ORM's so i have implemented js-data parent relations.
A belongsTo
relationship should always exist at the other end of a hasOne or hasMany
relationship. It is there purely as a convenience so that we can navigate UP to object hierarchy from Children to Parents.
So in you example above when the server did not include and relationships information in its response it was deserialized correctly. However when the relationships were returned in the response. We could not deserialize it correctly because we did not have the js-data definitions of the relationship.
Rather than failing silently and loosing data. I chose to fail the deserialization and raise and error.
As you pointed out the solution to your problem is to correctly define the relationship as a Child relationship!!
After explaining this i realize that there was quite a bit of work that i did to support these parent links. I inspect the self link and extract the parent id from the link. I now realize that this is not necessary.
If we only use belongsTo
at the other end of a hasOne or hasMany
then the belongsTo
links will take care of themselves when we set the foreign key on the parent's child relationships.
This would require the localKey name of the child's belongsTo
relationship to match the foreignKey name of the parents hasOne or hasMany
as it should do any way!
I asked about belongsTo vs hasOne in the js-data Slack. This was their response:
Often times
belongsTo
is important in situations where you need to know which item needs to be created first in the database due to foreign key constraints. I wouldn't be able to create the Users object without specifying the parent Account, withbelongsTo
, that would be very easy to see.hasOne
I would allow that User to exist even without a parent Account
However, I agree with you that if belongsTo
introduces complication then I can just use hasOne
.
There's no problem using belongsTo
but it should not be used on its own without having a hasOne or hasMany referring to it!!
This is something i was thinking about, is belongsTo
actually intended for defining a relationship or does it just add additional information/constraint to an existing relationship and allow the relationship to be traversed in both directions parent -> child -> parent.
js-data represents data in the same way as a relational database so i guess belongsTo
introduces a localKey in just the same way that a foreign key is added to a foreign object.
So actually if i don't change anything belongsTo
relationships will work without a corresponding hasOne or hasMany.
Just understand that a belongsTo
is the inverse relationship of a hasOne
these relationships operate between the same objects but in opposite directions.
Actually can we close this one?