defmodule Serene do @moduledoc """ Serene """ @annotations [:create, :read, :update, :delete] defmacro __using__(_) do quote do import unquote(__MODULE__) @before_compile unquote(__MODULE__) @on_definition unquote(__MODULE__) Module.register_attribute(__MODULE__, :actions, accumulate: true) end end defmacro __before_compile__(_) do quote do def __actions__, do: @actions end end def __on_definition__(%Macro.Env{module: module}, :def, fun, args, _, _) do case find_annotation(module, @annotations) do {action, resource} -> Module.put_attribute( module, :actions, {action, resource, {module, fun, clean_args(args)}} ) _ -> nil end end def __on_definition__(_, _, _, _, _, _), do: nil defp find_annotation(_, []), do: nil defp find_annotation(module, [annotation | rest]) do if value = Module.get_attribute(module, annotation) do Module.delete_attribute(module, annotation) {annotation, value} else find_annotation(module, rest) end end defp clean_args(args) do Enum.map(args, fn {name, _meta, _default} -> name end) end end