BlairAllegroTech / js-data-jsonapi

JsonApi Adapter for js-data

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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 , hasManyrelationships 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, with belongsTo, 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?