diff --git a/lib/ja_serializer/builder/resource_identifier.ex b/lib/ja_serializer/builder/resource_identifier.ex index ec94f86..0f5586c 100644 --- a/lib/ja_serializer/builder/resource_identifier.ex +++ b/lib/ja_serializer/builder/resource_identifier.ex @@ -22,7 +22,8 @@ defmodule JaSerializer.Builder.ResourceIdentifier do defp do_build(data, context, definition) do %__MODULE__{ type: find_type(data, context, definition), - id: find_id(data, context, definition) + id: find_id(data, context, definition), + meta: get_meta(data, context, definition) } end @@ -48,4 +49,14 @@ defmodule JaSerializer.Builder.ResourceIdentifier do end end + defp get_meta(_, _, %{identifier_meta: nil}), do: nil + defp get_meta( + destination_data, + %{data: source_data, serializer: serializer, conn: conn}, + %{identifier_meta: identifier_metadata_name}) + when is_atom(identifier_metadata_name) do + apply(serializer, identifier_metadata_name, [source_data, destination_data, conn]) + end + + defp get_meta(_destination_data, _context, _definition), do: nil end diff --git a/lib/ja_serializer/formatter/resource_identifier.ex b/lib/ja_serializer/formatter/resource_identifier.ex index a6024d2..7492d7e 100644 --- a/lib/ja_serializer/formatter/resource_identifier.ex +++ b/lib/ja_serializer/formatter/resource_identifier.ex @@ -1,8 +1,13 @@ defimpl JaSerializer.Formatter, for: JaSerializer.Builder.ResourceIdentifier do def format(resource) do - %{ + required_attributes = %{ "id" => to_string(resource.id), "type" => resource.type } + + add_meta(required_attributes, resource) end + + defp add_meta(resource, %{meta: nil}), do: resource + defp add_meta(resource, %{meta: meta}), do: Map.put(resource, "meta", meta) end diff --git a/lib/ja_serializer/relationship.ex b/lib/ja_serializer/relationship.ex index 1c86f49..7465e95 100644 --- a/lib/ja_serializer/relationship.ex +++ b/lib/ja_serializer/relationship.ex @@ -33,12 +33,14 @@ defmodule JaSerializer.Relationship do The fields are: - * `serializer` - A Serializer (often a PhoenixView) implementing the JaSerializer.Serializer behaviour. - * `include` - Should this relationship be included (sideloaded) by default. Overriden by `include` opt to JaSerializer.format/4 - * `data` - A list of structs representing the data. - * `identifiers` - Should "resource identifiers be included, options are `:when_included` and `:always`. Defaults to `:when_included` - * `links` - A keyword list of links, `self` and `related` are most common. - * `name` - Name of the relationship, automatically set. + * `serializer` - A Serializer (often a PhoenixView) implementing the JaSerializer.Serializer behaviour. + * `include` - Should this relationship be included (sideloaded) by default. Overriden by `include` opt to JaSerializer.format/4 + * `data` - A list of structs representing the data. + * `identifiers` - Should "resource identifiers be included, options are `:when_included` and `:always`. Defaults to `:when_included` + * `links` - A keyword list of links, `self` and `related` are most common. + * `name` - Name of the relationship, automatically set. + * `identifier_meta` - An atom referring to a function on the serializer. If specified, it is called with the source record, the destination record, and the conn. + Used when defining relationships without the DSL using the JaSerializer.relationships/2 callback. For example: @@ -57,25 +59,27 @@ defmodule JaSerializer.Relationship do of relationships. """ defstruct [ - links: [], - type: nil, - serializer: nil, - include: false, - data: nil, - identifiers: :when_included, - name: nil + links: [], + type: nil, + serializer: nil, + include: false, + data: nil, + identifiers: :when_included, + name: nil, + identifier_meta: nil ] @doc false def from_dsl(name, dsl_opts) do %__MODULE__{ - links: dsl_opts[:links] || [], - type: dsl_opts[:type], - serializer: dsl_opts[:serializer], - include: dsl_opts[:include], - data: dsl_opts[:data] || name, - identifiers: dsl_opts[:identifiers] || :when_included, - name: name + links: dsl_opts[:links] || [], + type: dsl_opts[:type], + serializer: dsl_opts[:serializer], + include: dsl_opts[:include], + data: dsl_opts[:data] || name, + identifiers: dsl_opts[:identifiers] || :when_included, + identifier_meta: dsl_opts[:identifier_meta] || nil, + name: name } end end @@ -86,13 +90,13 @@ defmodule JaSerializer.Relationship do The fields are: - * `serializer` - A Serializer (often a PhoenixView) implementing the JaSerializer.Serializer behaviour. - * `include` - Should this relationship be included (sideloaded) by default. Overriden by `include` opt to JaSerializer.format/4 - * `data` - A struct representing the data for serialization. - * `identifiers` - Should "resource identifiers be included, options are `:when_included` and `:always`. Defaults to `:when_included` - * `links` - A keyword list of links, `self` and `related` are most common. - * `name` - Name of the relationship, automatically set. - + * `serializer` - A Serializer (often a PhoenixView) implementing the JaSerializer.Serializer behaviour. + * `include` - Should this relationship be included (sideloaded) by default. Overriden by `include` opt to JaSerializer.format/4 + * `data` - A struct representing the data for serialization. + * `identifiers` - Should "resource identifiers be included, options are `:when_included` and `:always`. Defaults to `:when_included` + * `links` - A keyword list of links, `self` and `related` are most common. + * `name` - Name of the relationship, automatically set. + * `identifier_meta` - An atom referring to a function on the serializer. If specified, it is called with the source record, the destination record, and the conn. Used when defining relationships without the DSL using the JaSerializer.relationships/2 callback. For example: @@ -111,25 +115,27 @@ defmodule JaSerializer.Relationship do of relationships. """ defstruct [ - links: [], - type: nil, - serializer: nil, - include: false, - data: nil, - identifiers: :always, - name: nil + links: [], + type: nil, + serializer: nil, + include: false, + data: nil, + identifiers: :always, + name: nil, + identifier_meta: nil ] @doc false def from_dsl(name, dsl_opts) do %__MODULE__{ - links: dsl_opts[:links] || [], - type: dsl_opts[:type], - serializer: dsl_opts[:serializer], - include: dsl_opts[:include], - data: dsl_opts[:data] || name, - identifiers: dsl_opts[:identifiers] || :always, - name: name + links: dsl_opts[:links] || [], + type: dsl_opts[:type], + serializer: dsl_opts[:serializer], + include: dsl_opts[:include], + data: dsl_opts[:data] || name, + identifiers: dsl_opts[:identifiers] || :always, + identifier_meta: dsl_opts[:identifier_meta] || nil, + name: name } end end