Current section

Files

Jump to
thetvdb lib model.ex
Raw

lib/model.ex

defmodule TheTVDB.Model do
@moduledoc false
defmacro __using__(_opts) do
quote do
import TheTVDB.Model
end
end
defmacro model(block) do
quote do
Module.register_attribute(__MODULE__, :model_fields, accumulate: true, persist: false)
unquote(block)
defstruct (Module.get_attribute(__MODULE__, :model_fields) |> Enum.map(&elem(&1, 0)))
@type t :: %__MODULE__{}
@doc false
def from_json(data) when is_map(data) do
@model_fields
|> Enum.reduce(%__MODULE__{}, fn {name, api_name}, acc ->
val = Map.get(data, api_name)
Map.put(acc, name, val)
end)
end
end
end
defmacro field(api_name) do
name = api_name_to_snake_case(api_name)
quote do
metadata = {unquote(name), unquote(api_name)}
Module.put_attribute(__MODULE__, :model_fields, metadata)
end
end
defp api_name_to_snake_case(name) do
name
|> String.to_charlist
|> Enum.reduce([], fn c, acc ->
if c >= 65 && c <= 90 do
[[c + 32, ?_] | acc]
else
[c | acc]
end
end)
|> String.Chars.to_string
|> String.reverse
|> String.to_atom
end
end