Skip to content
This repository has been archived by the owner on Jan 2, 2023. It is now read-only.

Non-existent one-to-one relationships #94

Closed
johnmaguire opened this issue Apr 20, 2016 · 4 comments
Closed

Non-existent one-to-one relationships #94

johnmaguire opened this issue Apr 20, 2016 · 4 comments

Comments

@johnmaguire
Copy link

johnmaguire commented Apr 20, 2016

Hi there,

I'm taking a look at this part of the spec on relationships.

Resource linkage MUST be represented as one of the following:

  • null for empty to-one relationships.
  • an empty array ([]) for empty to-many relationships.
  • a single resource identifier object for non-empty to-one relationships.
  • an array of resource identifier objects for non-empty to-many relationships.

I'm not sure if my understanding is incorrect or not. My URL looks like this: GET /v1/devices?include=group

I have done this to get the "relationships" key to show up for all items:

    public function group($device)
    {
        return new Relationship(
            $device['group_id'] ? new Resource([
                'id' => $device['group_id'],
                'name' => $device['group_name'],
            ], new GroupSerializer) : null
        );
    }

Originally I tried to return null instead of a Relationship, but that removes the "relationships" block entirely. The only problem with the above solution is that it seems to only support "X-to-many" relationships. In other words, the response from the API looks like this:

"relationships": {
    "group": []
}

I believe that in reality, I want it to look like this:

"relationships": {
    "group": null
}

Is there any way to get this result? Thank you so much for this library! It's very flexible and useful.

@johnmaguire
Copy link
Author

I will note, some other things I tried:

  1. Returning "null" from group() causes the "relationships" object to disappear. (I don't think this is desired behavior.)
  2. I can't really specify "null" to new Resource as the serializer will not work.

@tobyzerner
Copy link
Owner

tobyzerner commented May 26, 2016

Thanks for the detailed report.

I've implemented a solution, which looks like this:

    public function emptyToOne($device)
    {
        return new Relationship(new EmptyResource);
    }

    public function emptyToMany($device)
    {
        return new Relationship(new EmptyCollection);
    }

i.e. To return an empty to-one relationship, pass an EmptyResource instance as the Relationship data.
To return an empty to-many relationship, pass an EmptyCollection instance as the Relationship data. (Passing a Collection with an empty array will work too.)

Why necessitate an EmptyResource object rather than just passing null as the Relationship data? Because there are times where the user may not wish to include the data key in the relationship object at all, instead filling it with links or meta – null data value is reserved for this case.

Please let me know if this works for you!

Scratch that! I found an easier way: simply returning null as the resource identifier if the data is null. So it'll look like this:

    public function emptyToOne($device)
    {
        return new Relationship(new Resource(null, new Serializer));
    }

    public function emptyToMany($device)
    {
        return new Relationship(new Collection([], new Serializer));
    }

tobyzerner added a commit that referenced this issue May 26, 2016
Since the natural thing to do is:

    return new Relationship(new Resource($data, new Serializer));

where $data may or may not be null. Now if $data is null, the resource identifier will be returned as null too, indicating an empty relationship.
@johnmaguire
Copy link
Author

👍 This works great, thank you!

@nubs
Copy link
Contributor

nubs commented May 27, 2016

Agreed - It worked exactly like expected. Will there be a new version of tobscure/json-api released soon?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants