Alembic v1.0.0 Alembic.ResourceLinkage

Resource linkage in a compound document allows a client to link together all of the included resource objects without having to GET any URLs via links.

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.

JSON API - Document Structure - Resource Objects - Resource Linkage

Summary

Functions

Converts a resource linkage to one or more Alembic.ResoureIdentifier.t

Functions

from_json(json, error_template)

Specs

Converts a resource linkage to one or more Alembic.ResoureIdentifier.t.

To-one

A to-one resource linkage, when present, can be a single Alembic.Resource.t or Alembic.ResourceIdentifier.t

A JSON object is assumed to be an resource object if it has "attributes"

iex> Alembic.ResourceLinkage.from_json(
...>   %{
...>     "attributes" => %{
...>       "name" => "Alice"
...>     },
...>     "id" => "1",
...>     "type" => "author"
...>   },
...>   %Alembic.Error{
...>     meta: %{
...>       "action" => :create,
...>       "sender" => :client
...>     },
...>     source: %Alembic.Source{
...>       pointer: "/data/relationships/author/data"
...>     }
...>   }
...> )
{
  :ok,
  %Alembic.Resource{
    attributes: %{
      "name" => "Alice"
    },
    id: "1",
    type: "author"
  }
}

Or if the JSON object has "relationships"

iex> Alembic.ResourceLinkage.from_json(
...>   %{
...>     "id" => "1",
...>     "relationships" => %{
...>       "author" => %{
...>         "data" => %{
...>           "id" => "1",
...>           "type" => "author"
...>         }
...>       }
...>     },
...>     "type" => "post"
...>   },
...>   %Alembic.Error{
...>     meta: %{
...>       "action" => :create,
...>       "sender" => :client
...>     },
...>     source: %Alembic.Source{
...>       pointer: "/data"
...>     }
...>   }
...> )
{
  :ok,
  %Alembic.Resource{
    id: "1",
    relationships: %{
      "author" => %Alembic.Relationship{
        data: %Alembic.ResourceIdentifier{
          id: "1",
          meta: nil,
          type: "author"
        }
      }
    },
    type: "post"
  }
}

If neither "attributes" nor "relationships" is present, then JSON object is assumed to be an Alembic.ResourceIdentifier.t.

iex> Alembic.ResourceLinkage.from_json(
...>   %{
...>     "id" => "1",
...>     "type" => "author"
...>   },
...>   %Alembic.Error{
...>     source: %Alembic.Source{
...>       pointer: "/data/relationships/author/data"
...>     }
...>   }
...> )
{
  :ok,
  %Alembic.ResourceIdentifier{
    id: "1",
    type: "author"
  }
}

An empty to-one resource linkage can be signified with nil, which would have been null in the original JSON.

iex> Alembic.ResourceLinkage.from_json(
...>   nil,
...>   %Alembic.Error{
...>     source: %Alembic.Source{
...>       pointer: "/data/relationships/author/data"
...>     }
...>   }
...> )
{:ok, nil}

To-many

A to-many resource linkage, when present, can be a list of Alembic.Resource.t.

iex> Alembic.ResourceLinkage.from_json(
...>   [
...>     %{
...>       "attributes" => %{
...>         "text" => "First Post!"
...>       },
...>       "id" => "1",
...>       "relationships" => %{
...>         "comments" => %{
...>           "data" => [
...>             %{
...>               "id" => "1",
...>               "type" => "comment"
...>             }
...>           ]
...>         }
...>       },
...>       "type" => "post"
...>     }
...>   ],
...>   %Alembic.Error{
...>     meta: %{
...>       "action" => :create,
...>       "sender" => :client
...>     },
...>     source: %Alembic.Source{
...>       pointer: "/data"
...>     }
...>   }
...> )
{
  :ok,
  [
    %Alembic.Resource{
      attributes: %{
        "text" => "First Post!"
      },
      id: "1",
      links: nil,
      relationships: %{
        "comments" => %Alembic.Relationship{
          data: [
            %Alembic.ResourceIdentifier{
              id: "1",
              type: "comment"
            }
          ]
        }
      },
      type: "post"
    }
  ]
}

Or a list of Alembic.ResourceIdentifier.t.

iex> Alembic.ResourceLinkage.from_json(
...>   [
...>     %{
...>       "id" => "1",
...>       "type" => "post"
...>     }
...>   ],
...>   %Alembic.Error{
...>     source: %Alembic.Source{
...>       pointer: "/data"
...>     }
...>   }
...> )
{
  :ok,
  [
    %Alembic.ResourceIdentifier{
      id: "1",
      type: "post"
    }
  ]
}

A mix of resources and resource identifiers is an error

iex> Alembic.ResourceLinkage.from_json(
...>   [
...>     %{
...>       "attributes" => %{
...>         "text" => "First Post!"
...>       },
...>       "id" => "1",
...>       "type" => "post"
...>     },
...>     %{
...>       "id" => "2",
...>       "type" => "post"
...>     }
...>   ],
...>   %Alembic.Error{
...>     meta: %{
...>       "action" => :create,
...>       "sender" => :client
...>     },
...>     source: %Alembic.Source{
...>       pointer: "/data"
...>     }
...>   }
...> )
{
  :error,
  %Alembic.Document{
    errors: [
      %Alembic.Error{
        detail: "`/data` type is not resource linkage",
        meta: %{
          "type" => "resource linkage"
        },
        source: %Alembic.Source{
          pointer: "/data"
        },
        status: "422",
        title: "Type is wrong"
      }
    ]
  }
}

An empty to-many resource linkage can be signified with [].

iex> Alembic.ResourceLinkage.from_json(
...>   [],
...>   %Alembic.Error{
...>     source: %Alembic.Source{
...>       pointer: "/data/relationships/comments/data"
...>     }
...>   }
...> )
{:ok, []}

Invalid

If the json isn’t any of the above, valid formats, then a type error will be returned

iex> Alembic.ResourceLinkage.from_json(
...>   "that resource over there",
...>   %Alembic.Error{
...>     source: %Alembic.Source{
...>       pointer: "/data/relationships/resource/data"
...>     }
...>   }
...> )
{
  :error,
  %Alembic.Document{
    errors: [
      %Alembic.Error{
        detail: "`/data/relationships/resource/data` type is not resource linkage",
        meta: %{
          "type" => "resource linkage"
        },
        source: %Alembic.Source{
          pointer: "/data/relationships/resource/data"
        },
        status: "422",
        title: "Type is wrong"
      }
    ]
  }
}