Simple resource relationships


#1

Hi,

I’m trying to wrap my head around resource relationships and what the proper object properties should be, serialization-wise, and I need some help. But first, let me give you a little bit of context.

I have two resources which have a simple one-to-many relationship: states and cities; so a given state can have any number of cities, and a city should belong to one and only one state. I think that best practices dictate that, from the URLs point of view, these two resources should be published like:

/states
/states/:stateId
/states/:stateId/cities
/states/:stateId/cities/:cityId

In my case it must not be like that since the requirements for this API specify that, while cities are logically contained in states, their URLs should be under the root. That means that the above example of URLs should be like:

/states
/states/:stateId
/cities
/cities/:cityId

This is perfectly doable, I think, the difference being that now a city resource should explicitly contain the state to which it belongs.

I have read the spec a couple of times, but I’m having trouble visualizing the way things will work. By the way, I think that having a generalized and standarized relationships member is simply genius. I seems to me that potentially I could easily relate any to resource to another and provide the same mechanism.

Anyway, here’s what I have. When fetching a single state resource:

{
  "data": {
    "type": "states",
    "id": "807ee0e0-d756-4d5d-84b7-d49b507221d4",
    "attributes": {
      "name": "North Carolina",
      "motto": "To be, rather than to seem"
    },
    "relationships": {
      "cities": {
        "links": {
          "self": "/states/807ee0e0-d756-4d5d-84b7-d49b507221d4/relationships/cities"
        }
      }
    },
    "links": {
      "self": "/states/807ee0e0-d756-4d5d-84b7-d49b507221d4"
    }
  }
}

And when fetching a single city:

{
  "data": {
    "type": "cities",
    "id": "f0c5bc1f-3872-438c-8f42-583c50cc2ea6",
    "attributes": {
      "name": "Fayetteville"
    },
    "relationships": {
      "states": {
        "links": {
          "self": "/cities/f0c5bc1f-3872-438c-8f42-583c50cc2ea6/relationships/states"
        }
      }
    },
    "links": {
      "self": "/cities/f0c5bc1f-3872-438c-8f42-583c50cc2ea6"
    }
  }
}

(This second object is very much like the previous one, except that types are reversed.) According to the spec, using the .../relationships/... URLs as resources, I can manipulate the relationships, no matter if it is a to-one or a to-many (that’s what I understood, at least.) If I can do that, what’s the use of related in the links member of a relationship definition?

Of course, if I am grossly mistaken about the whole shebang, could you please point it out?

Note, however, that there are constraints that should be enforced by the API. For instance, it is impossible to remove a to-one relationship from a city to a state. It can be changed, but not removed. Likewise, creating a city implies including the proper relationship data. I have not mentioned it before because right now I’m trying to understand the basics.

Thanks a lot,
Carlos.


#2

The related attribute gives you a way to manipulate the related resource directly, not the relationship. It is the difference between adding/removing a city from a state (via the relationships.states.links.self) and viewing/changing the attributes of a state (via relationships.states.links.related: "/states/:stateId").

Hope this helps.