Skip to content

Instantly share code, notes, and snippets.

@tiagopog
Created March 21, 2018 13:27
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 tiagopog/95b13731d1dd6163bb2236bb3d466456 to your computer and use it in GitHub Desktop.
Save tiagopog/95b13731d1dd6163bb2236bb3d466456 to your computer and use it in GitHub Desktop.
Elixir - Define struct dynamically at compile-time.
defmodule Iugu.Resource do
@moduledoc """
Mixin module to easily include all the common functionality across the resources.
"""
defmacro __using__([name: resource, actions: actions]) do
quote do
@derive [Poison.Encoder]
@resource unquote(resource)
defstruct unquote(fields(resource))
Module.eval_quoted(__MODULE__, unquote(define_actions(actions)), [], __ENV__)
end
end
@spec define_actions(list) :: list
def define_actions(actions) do
actions
|> Enum.map(fn(action) -> define_action(action) end)
end
@spec define_action(atom) :: {atom, list, list}
def define_action(:list) do
quote do
@spec list(Iugu.Request.t | map) :: Iugu.Request.get_response
def list(params \\ %{})
def list(%Iugu.Request{} = request) do
%Iugu.Request{request | path: @resource}
|> Iugu.Request.get(__MODULE__, :collection)
end
def list(params) when is_map(params) do
%Iugu.Request{params: params}
|> list()
end
end
end
def define_action(:show) do
quote do
@spec show(String.t) :: Iugu.Request.get_response
def show(id) do
%Iugu.Request{path: "#{@resource}/#{id}"}
|> Iugu.Request.get(__MODULE__, :single)
end
end
end
def define_action(:create) do
quote do
@spec create(map) :: Iugu.Request.post_response
def create(%{} = data) do
case Poison.encode(data) do
{:ok, json} ->
%Iugu.Request{path: @resource, body: json}
|> Iugu.Request.post(__MODULE__)
{status, result} ->
{status, result}
end
end
end
end
@spec fields(String.t) :: list
def fields(resource) do
Application.get_env(:iugu, String.to_atom(resource))
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment