Skip to content

Commit

Permalink
📎 version bump
Browse files Browse the repository at this point in the history
  • Loading branch information
Aleksei Matiushkin committed Apr 16, 2024
1 parent f170ea3 commit 9813cbe
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 21 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ end
I suggest adding [`boundary`](https://hexdocs.pm/boundary) as a dependency since that is used in this project.

## Changelog
* `1.4.1` — allow functions of arity 1 in `content` as coercers in a call to `Estructura.Aston.coerce/2`
* `1.4.0` — allow coercers in a call to `Estructura.Aston.coerce/2`
* `1.3.0` — calculated fields for `Estructura` and `Estructura.Nested`
* `1.2.12` — export type from `Estructura.Nested`
Expand Down
44 changes: 25 additions & 19 deletions lib/estructura/aston.ex
Original file line number Diff line number Diff line change
Expand Up @@ -131,35 +131,41 @@ defmodule Estructura.Aston do
@doc """
Coerces the deeply nested map to an instance of nested `Estructura.Aston`
"""
@spec coerce(any(), keyword()) :: {:ok, value} | {:error, reason}
@spec coerce(any(), keyword(), nil | any()) :: {:ok, value} | {:error, reason}
when value: any(), reason: String.t()
def coerce(term, opts \\ [])
def coerce(term, opts \\ [], root \\ nil)

def coerce(%Aston{} = tree, opts),
do: tree |> Map.from_struct() |> coerce(opts)
def coerce(tree, opts, nil),
do: coerce(tree, opts, tree)

def coerce(nil, opts),
do: apply_coercers(nil, opts)
def coerce(%Aston{} = tree, opts, root),
do: tree |> Map.from_struct() |> coerce(opts, root)

def coerce(bool_node, opts) when bool_node in [true, false],
do: apply_coercers(bool_node, opts)
def coerce(f, opts, root) when is_function(f, 1),
do: apply_coercers(f.(root), opts, root)

def coerce(number_node, opts) when is_number(number_node),
do: apply_coercers(number_node, opts)
def coerce(nil, opts, root),
do: apply_coercers(nil, opts, root)

def coerce(text_node, opts) when is_binary(text_node),
do: apply_coercers(text_node, opts)
def coerce(bool_node, opts, root) when bool_node in [true, false],
do: apply_coercers(bool_node, opts, root)

def coerce(list, opts) when is_list(list) do
result = Enum.map(list, &coerce(&1, opts))
def coerce(number_node, opts, root) when is_number(number_node),
do: apply_coercers(number_node, opts, root)

def coerce(text_node, opts, root) when is_binary(text_node),
do: apply_coercers(text_node, opts, root)

def coerce(list, opts, root) when is_list(list) do
result = Enum.map(list, &coerce(&1, opts, root))

case Enum.split_with(result, &match?({:error, _}, &1)) do
{[], result} -> {:ok, Enum.map(result, &elem(&1, 1))}
{errors, _} -> {:error, Enum.map_join(errors, "\n", &elem(&1, 1))}
end
end

def coerce(%{} = map, opts) do
def coerce(%{} = map, opts, root) do
name = Map.get_lazy(map, :name, fn -> Map.get(map, "name") end)
{key_prefix, opts} = Keyword.pop(opts, :key_prefix, [])
key_prefix = key_prefix ++ List.wrap(name)
Expand All @@ -185,7 +191,7 @@ defmodule Estructura.Aston do
|> Enum.reduce(%Aston{}, fn {k, v}, acc ->
k
|> case do
:content -> coerce(v, Keyword.put(opts, :key_prefix, key_prefix))
:content -> coerce(v, Keyword.put(opts, :key_prefix, key_prefix), root)
_ -> {:ok, v}
end
|> case do
Expand All @@ -200,12 +206,12 @@ defmodule Estructura.Aston do
{:error, Exception.message(e)}
end

def coerce(term, opts),
def coerce(term, opts, _root),
do: {:error, "Unknown term at #{inspect(opts)}: ‹#{inspect(term)}›"}

@spec apply_coercers(any(), keyword()) :: {:ok, value} | {:error, reason}
@spec apply_coercers(any(), keyword(), any()) :: {:ok, value} | {:error, reason}
when value: any(), reason: String.t()
defp apply_coercers(term, opts) do
defp apply_coercers(term, opts, _root) do
key = Keyword.get(opts, :key_prefix)

opts
Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ defmodule Estructura.MixProject do
use Mix.Project

@app :estructura
@version "1.4.0"
@version "1.4.1"

def project do
[
Expand Down
5 changes: 4 additions & 1 deletion test/estructura/aston_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ defmodule Estructura.Aston.Test do
content: %{
name: ["Baz", "Baz2"],
content: [
%{content: [true, 3.14], name: "Deep1"},
%{
content: [fn data -> data.name == "Bar" end, 3.14],
name: "Deep1"
},
%{content: ["string", nil], name: "Deep2"},
%Aston{name: "Deep3", attributes: %{}, content: ["20240327"]}
]
Expand Down

0 comments on commit 9813cbe

Please sign in to comment.