Alembic v1.0.0 Alembic.Relationship

Members of the relationships object (“relationships”) represent references from the resource object in which it’s defined to other resource objects.

Relationships may be to-one or to-many.

JSON API - Document Structure - Resource Objects - Relationships

Summary

Types

t()

A “relationship object” MUST contain at least one of the following:

  • links - a links object containing at least one of the following:

    • self - a link for the relationship itself (a “relationship link”). This link allows the client to directly manipulate the relationship. For example, removing an author through an article’s relationship URL would disconnect the person from the article without deleting the people resource itself. When fetched successfully, this link returns the linkage for the related resources as its primary data. (See Fetching Relationships.)
    • related - a related resource link
  • data - resource linkage
  • meta - a meta object that contains non-standard meta-information about the relationship.

JSON API - Document Structure - Resource Objects - Relationships

Types

t :: %Alembic.Relationship{data: [resource_identifier] | resource_identifier, links: Alembic.Links.links, meta: Alembic.meta}

A “relationship object” MUST contain at least one of the following:

  • links - a links object containing at least one of the following:

    • self - a link for the relationship itself (a “relationship link”). This link allows the client to directly manipulate the relationship. For example, removing an author through an article’s relationship URL would disconnect the person from the article without deleting the people resource itself. When fetched successfully, this link returns the linkage for the related resources as its primary data. (See Fetching Relationships.)
    • related - a related resource link
  • data - resource linkage
  • meta - a meta object that contains non-standard meta-information about the relationship.

JSON API - Document Structure - Resource Objects - Relationships

Functions

from_json(json, error_template)

Specs

from_json(Alembic.json_object, Alembic.Error.t) ::
  {:ok, t} |
  Alembic.FromJson.error
from_json(nil | true | false | list | float | integer | String.t, Alembic.Error.t) :: Alembic.FromJson.error

Relationships

A non-object will be matched, but return an error.

iex> Alembic.Relationship.from_json(
...>   "1",
...>   %Alembic.Error{
...>     source: %Alembic.Source{
...>       pointer: "/data/relationships/author"
...>     }
...>   }
...> )
{
  :error,
  %Alembic.Document{
    errors: [
      %Alembic.Error{
        detail: "`/data/relationships/author` type is not relationship",
        meta: %{
          "type" => "relationship"
        },
        source: %Alembic.Source{
          pointer: "/data/relationships/author"
        },
        status: "422",
        title: "Type is wrong"
      }
    ]
  }
}

An object without any of the members will show them as all missing

iex> Alembic.Relationship.from_json(
...>   %{},
...>   %Alembic.Error{
...>     source: %Alembic.Source{
...>       pointer: "/data/relationships/author"
...>     }
...>   }
...> )
{
  :error,
  %Alembic.Document{
    errors: [
      %Alembic.Error{
        detail: "At least one of the following children of `/data/relationships/author` must be present:\n" <>
                "data\n" <>
                "links\n" <>
                "meta",
        meta: %{
          "children" => [
            "data",
            "links",
            "meta"
          ]
        },
        source: %Alembic.Source{
          pointer: "/data/relationships/author"
        },
        status: "422",
        title: "Not enough children"
      }
    ]
  }
}

Resource Linkage

To-one

"data" can be a single resource identifier

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

An empty to-one relationship can be signified with nil for "data"

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

To-many

"data" can be a list of resource identifiers

iex> Alembic.Relationship.from_json(
...>   %{
...>     "data" => [
...>       %{"id" => "1", "type" => "comment"},
...>       %{"id" => "2", "type" => "comment"}
...>     ]
...>   },
...>   %Alembic.Error{
...>     source: %Alembic.Source{
...>       pointer: "/data/relationships/comments"
...>     }
...>   }
...> )
{
  :ok,
  %Alembic.Relationship{
    data: [
      %Alembic.ResourceIdentifier{id: "1", type: "comment"},
      %Alembic.ResourceIdentifier{id: "2", type: "comment"}
    ]
  }
}

An empty to-many relationship can be signified with []

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

Invalid

There are actual, invalid values for resource linkages, such as strings and numbers

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

Links

"links" if present, must be an object

iex> Alembic.Relationship.from_json(
...>   %{"links" => ["http://example.com"]},
...>   %Alembic.Error{
...>     source: %Alembic.Source{
...>       pointer: "/data/relationships/website"
...>     }
...>   }
...> )
{
  :error,
  %Alembic.Document{
    errors: [
      %Alembic.Error{
        detail: "`/data/relationships/website/links` type is not links object",
        meta: %{
          "type" => "links object"
        },
        source: %Alembic.Source{
          pointer: "/data/relationships/website/links"
        },
        status: "422",
        title: "Type is wrong"
      }
    ]
  }
}

Because the “links” name are free-form, they remain strings

iex> Alembic.Relationship.from_json(
...>   %{"links" => %{"example" => "http://example.com"}},
...>   %Alembic.Error{
...>     source: %Alembic.Source{
...>       pointer: "/data/relationships/website"
...>     }
...>   }
...> )
{
  :ok,
  %Alembic.Relationship{
    links: %{
      "example" => "http://example.com"
    }
  }
}

“links” can be mix of String.t URLs and Alembic.Link.t objects

iex> Alembic.Relationship.from_json(
...>   %{
...>     "links" => %{
...>       "link_object" => %{
...>          "href" => "http://example.com/link_object/href"
...>       },
...>       "string" => "http://example.com/string"
...>     }
...>   },
...>   %Alembic.Error{
...>     source: %Alembic.Source{
...>       pointer: "/data/relationships/website"
...>     }
...>   }
...> )
{
  :ok,
  %Alembic.Relationship{
    links: %{
      "link_object" => %Alembic.Link{
        href: "http://example.com/link_object/href"
      },
      "string" => "http://example.com/string"
    }
  }
}