Skip to content

Instantly share code, notes, and snippets.

@alanpeabody
Last active August 29, 2015 14:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alanpeabody/1f4f1564ab80338a26ed to your computer and use it in GitHub Desktop.
Save alanpeabody/1f4f1564ab80338a26ed to your computer and use it in GitHub Desktop.
JaSerializer Serialization Milestones

JaSerializer Roadmap

The initial release of JaSerializer successfully accomplishes it's mission; it serializes data to jsonapi.org format.

Roadmap:

  • Solidify/determine future of the DSL.
  • Better Ecto integration.
  • A Phoenix view integration.

Future of DSL

A few members of the Elixir community have indicated the DSL based approach isn't recommended. This is an exercise in embracing that critisim and seeing how much of a DSL can be removed w/o sacrificing important functionality.

Desired functionality:

  • Define what attributes the serializer exposes.
  • Add custom logic/presenter functions.
  • Controll on a per conn/model basis what is serialized.

Discussion Points

Definition vs Data

AMS and the existing DSL is mostly a 'descriptive' dsl. The DSL establishes how to serialize something. An alternative approach would be defining a behaviour that expects the actual data to be serialized to be returned. An example of this is the attributes/2 function in behaviour_dsl_2.ex which expects an actual map to be returned, vs the other two examples which expect lists to be returned.

type, location, id, and attributes are examples where returning the actual data is straightforward.

However, relationships are fairly complicated and perhaps less easy to easily return as data.

Consistency

The API should be consistent for all functions. Mixing macro dsl w/ behaviour definition or definition dsl with data dsl can create confusion.

Overriding data/presenter functions

Importantly the serialization layer is the only place where the curent user (via conn) and the model are combined. This is a super important feature and means we must be able to inject values to be serialized that were not available before. It also means we should be able to restrict the attributes returned based on the user/conn.

Ecto Integration

  • Relationships should just work w/o defining a custom function.

Phoenix Integration

  • A view version of JaSerializer that can be used in as a phoenix view.
defmodule Example.Serializers.V1.Article do
use JaSerializer
def type, do: "article"
def location, do: "/v1/articles/:id"
def relationships(model, conn), do [
has_one(:author, model, conn, link: "/v1/author/:author_id", type: "person"),
has_many(:comments, model, conn, link: "/v1/articles/:id/comments"),
has_many(:tags, model, conn, include: Example.Serializers.V1.Tag)
]
def attributes(model, _conn) do
model
|> Map.take([:title, :excerpt, :body])
|> Map.merge(%{
excerpt: excerpt(model)
})
end
def excerpt(model) do
model.body |> String.split(".") |> List.first
end
end
defmodule Example.Serializers.V1.Article do
use JaSerializer
def type, do: "article"
def location, do: "/v1/articles/:id"
def relationships, do [
author: [link: "/v1/author/:author_id", type: "person"],
comments: [link: "/v1/articles/:id/comments"],
tags: [include: Example.Serializers.V1.Tag]
]
def attributes, do: [:title, :body]
def computed_attributes, do: [:excerpt]
def permitted_attributes(_model, _conn) do
attributes ++ computed_attributes #defaul (all)
end
def excerpt(model) do
model.body |> String.split(".") |> List.first
end
end
defmodule Example.Serializers.V1.Article do
use JaSerializer
serialize "article" do
location "/v1/articles/:id"
attributes [:title, :excerpt, :body]
has_one :author, link: "/v1/author/:author_id", type: "person"
has_many :comments, link: "/v1/articles/:id/comments"
has_many :tags, include: Example.Serializers.V1.Tag
end
relationships = [{:has_many, name, opts},]
def permitted_attributes(_model, _conn) do
__MODULE__.__attributes #default (all):
end
def excerpt(model) do
model.body |> String.split(".") |> List.first
end
end
defmodule Example.Serializers.V1.Article do
use JaSerializer
# def type, do: "article"
# def location, do: "/v1/articles/:id"
# def location, do: &(url_for(:article, &1))
attributes [:title, :excerpt, :body]
has_one :author, link: "/v1/author/:author_id", type: "person"
has_many :comments, link: "/v1/articles/:id/comments"
has_many :tags, include: Example.Serializers.V1.Tag
def excerpt(model) do
model.body |> String.split(".") |> List.first
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment