Last active
February 26, 2018 12:15
-
-
Save gorkunov/72aa06674330d9466d9d54cbb840ed57 to your computer and use it in GitHub Desktop.
This file contains hidden or 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 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