rosscado / raceready

Created for toolchain: https://console.bluemix.net/devops/toolchains/0fc11092-0119-4ab8-a5f0-6cbf19d20e03?env_id=ibm%3Ayp%3Aeu-gb
0 stars 0 forks source link

Resource Relationship Representation #58

Open rosscado opened 6 years ago

rosscado commented 6 years ago

How should the API model represent referenced entities, especially entities that are shared?

For example, a single Circuit entity may be referenced by many Event entities. Should the Event nest the Circuit as a circuit: {CIRCUIT} field, point to the external object's primary key circuit_id: {circuit_uuid}, or point to the object's URI circuit: {circuit_url}?

Options

  1. Embeded resources - fields.Nested
  2. Keyed resources - fields.String
  3. Hyperlinked resources - fields.Url

Hyperlinked Resources

Some consider the purest RESTful representation to require addressing resources by hyperlinks to their URIs. By responding with hyperlinks instead of primary keys the server doesn't require the client to have any implicit knowledge about how to use/lookup the primary keys.

Flask RestPlus represents such fields as fields.Url. Marshmallow represents them as HyperlinkRelated. Python Eve generates a HATEOAS links field by default, and returns primary keys unless directed to embed.

HATEOAS

According to strict hypermedia representational principles like HATEOAS relationships between resources should be represented as url-addressable links.

title: Lucan GP
id: {id}
links:
   self:
      href: /events/{id}
      rel: self
   organising_club:
      - href: /clubs/lrcc
        rel: club
   races:
      - href: /stages/{headline_race_id}
        rel: race
      - href: /stages/{a4_race_id}
        rel: race

The hypermedia principle theoretically supports programmatic navigation by clients by providing them with the complete set of permissible operations in every REST API response. E.g. GET /event/{id} is responded to with:

The hypermedia principle extends from the web paradigm where servers have little control over clients; They know little more than that their clients are web browsers that may navigate across the network of resources linked to in the server's responses.

In most practical applications, and certainly in this project's case, there is much more control over the client(s) and its requirements. For us there will be one client initially (in support of a web application with possible mobile application clients added later), a JavaScript library rendering application resources in a web UI.

Object Links

A compromise approach that adopts advantages of both hypermedia and domain-application principles is to federate resources and include links to each. 1 GET /events/{id}

title: Lucan GP
id: {id}
href: /events/{id}
organised_by:
   club:
      title: Lucan Road Cycling Club
      href: /clubs/lrcc
races:
   - href: /events/{id}/races/{stage_id_a123}
   - href: /events/{id}/races/{stage_id_a4W}

Originally posted by @rosscado in https://github.com/rosscado/raceready/issues/57#issuecomment-420972983

rosscado commented 5 years ago

Under the proposed Strict Object Links approach all complex objects that are individually addressable have id and href attributes.

Relationship Links by Default

Relationships to complex objects are represented with the href attribute only.

relation:
   href: url_for_object

Example:

club:
   href: /clubs/lrcc

id: A globally unique identifier href: A resources href attribute is always a function of the endpoint and id values

Nesting On Request Only

Complex objects are not embedded unless explicitly requested with embed query parameter /$resource?embed=($relation,...).