Last active
August 29, 2015 14:22
-
-
Save tjheeta/ae63f068656dddb03098 to your computer and use it in GitHub Desktop.
First pass for Ecto -> Json API - WIP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule JsonApi do | |
def filter_struct(obj) do | |
is_struct?(obj) or (is_list(obj) && is_struct?(Enum.at(obj,0))) | |
end | |
def is_struct?(obj) do | |
is_map(obj) && Map.get(obj, :__struct__) != nil | |
# ( obj.__struct__ == Ecto.Association.NotLoaded || | |
end | |
def json_api(obj) do | |
if is_list(obj) do | |
data = Enum.map(obj, &json_api_data(&1)) | |
%{ data: data } | |
else | |
json_api_data(obj) | |
end | |
end | |
def json_api_data(obj, filter \\ []) do | |
# Go one level deep while splitting out the structs | |
# If it's a struct, it should be under relationships and includes | |
{structures, attributes} = | |
Map.drop(obj, [:__meta__, :__struct__]) | |
|> Enum.partition( fn{k,v} -> | |
filter_struct(v) | |
end) | |
attributes = attributes |> Enum.into(%{}) | |
# Parse the structures to give some relationships | |
relationships = | |
structures | |
|> Enum.map( fn{k,v} -> | |
if ! is_list(v), do: v = [v] | |
data = Enum.reduce(v, [], fn(x, acc) -> | |
id = Map.get(x,:id) | |
if id, do: acc = acc ++ [%{"type": to_string(k), "id": id}] | |
end) | |
data | |
end) | |
|> List.flatten | |
|> Enum.reject(&is_nil(&1)) | |
# Ugly, but go over the included set from the structures one more time | |
included = | |
structures | |
|> Enum.map( fn{k,v} -> | |
if ! is_list(v), do: v = [v] | |
data = Enum.reduce(v, [], fn(x, acc) -> | |
id = Map.get(x,:id) | |
# find everything that isn't a struct and put it into a map | |
attributes= | |
x | |
|> Map.drop([:__meta__, :__struct__]) | |
|> Enum.reject(fn{k,v} -> | |
filter_struct(v) | |
end) | |
|> Enum.into(%{}) | |
if id, do: acc = acc ++ [%{"type": x.__meta__.source, "id": id, "attributes": attributes}] | |
end) | |
data | |
end) | |
|> List.flatten | |
|> Enum.reject(&is_nil(&1)) | |
# Generate first level object | |
%{ | |
type: obj.__meta__.source, | |
id: attributes[:id], | |
attributes: attributes, | |
links: %{ "self": "something" }, | |
relationships: relationships, | |
included: included | |
} | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment