Skip to content

Instantly share code, notes, and snippets.

@gorkunov
Last active February 26, 2018 12:15
Show Gist options
  • Save gorkunov/72aa06674330d9466d9d54cbb840ed57 to your computer and use it in GitHub Desktop.
Save gorkunov/72aa06674330d9466d9d54cbb840ed57 to your computer and use it in GitHub Desktop.
defmodule Params do
@moduledoc """
Provides Ecto.Schema for params parsing.
Example:
defmodule SearchParams do
use Params
params do
field(:text, :string)
field(:user_id, :integer)
field(:team_ids, {:array, :integer})
end
end
SearchParams.parse(%{"text => "bla", "user_id" => "123", "team_ids" => ["1", "2"]})
=> {:ok, %{text: "bla", user_id: 123, team_ids: [1, 2]}
"""
import Ecto.Changeset
defmacro params(do: definition) do
quote do
embedded_schema do
unquote(definition)
end
def parse(attrs, defaults \\ %{}) do
do_parse(__MODULE__, %__MODULE__{}, attrs, defaults)
end
end
end
def do_parse(module, struct, attrs, defaults) do
fields = module.__schema__(:fields) -- [:id]
changeset = cast(struct, attrs, fields)
case changeset do
%{valid?: false, errors: errors} ->
{:error, errors}
_ ->
{:ok, build_map(changeset, fields, defaults)}
end
end
defp build_map(changeset, fields, defaults) do
Enum.reduce(fields, %{}, fn field, acc ->
Map.put(acc, field, get_change(changeset, field, Map.get(defaults, field)))
end)
end
defmacro __using__(_) do
quote do
use Ecto.Schema
import ProsapientWeb.Params
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment