Current section

Files

Jump to
mongodb_ecto lib mongo_ecto conversions.ex
Raw

lib/mongo_ecto/conversions.ex

defmodule Mongo.Ecto.Conversions do
@moduledoc false
import Mongo.Ecto.Utils
def to_ecto_pk(%{__struct__: _} = value, _pk),
do: value
def to_ecto_pk(map, pk) when is_map(map) do
Enum.into(map, %{}, fn
{"_id", value} -> {Atom.to_string(pk), to_ecto_pk(value, pk)}
{key, value} -> {key, to_ecto_pk(value, pk)}
end)
end
def to_ecto_pk(list, pk) when is_list(list),
do: Enum.map(list, &to_ecto_pk(&1, pk))
def to_ecto_pk(value, _pk),
do: value
def inject_params(doc, params, pk) when is_keyword(doc),
do: document(doc, params, pk)
def inject_params(list, params, pk) when is_list(list),
do: map(list, &inject_params(&1, params, pk))
def inject_params({:^, _, [idx]}, params, pk),
do: elem(params, idx) |> inject_params(params, pk)
def inject_params(%{__struct__: _} = struct, _params, pk),
do: from_ecto_pk(struct, pk)
def inject_params(map, params, pk) when is_map(map),
do: document(map, params, pk)
def inject_params(value, _params, pk),
do: from_ecto_pk(value, pk)
def from_ecto_pk(%{__struct__: change, field: field, value: value}, pk)
when change in [Mongo.Ecto.ChangeMap, Mongo.Ecto.ChangeArray] do
case from_ecto_pk(value, pk) do
{:ok, value} -> {:ok, {field, value}}
:error -> :error
end
end
def from_ecto_pk(%{__struct__: _} = value, _pk),
do: {:ok, value}
def from_ecto_pk(map, pk) when is_map(map),
do: document(map, pk)
def from_ecto_pk(keyword, pk) when is_keyword(keyword),
do: document(keyword, pk)
def from_ecto_pk(list, pk) when is_list(list),
do: map(list, &from_ecto_pk(&1, pk))
def from_ecto_pk(value, _pk) when is_literal(value),
do: {:ok, value}
def from_ecto_pk(_value, _pk),
do: :error
defp document(doc, pk) do
map(doc, fn {key, value} ->
pair(key, value, pk, &from_ecto_pk(&1, pk))
end)
end
defp document(doc, params, pk) do
map(doc, fn {key, value} ->
pair(key, value, pk, &inject_params(&1, params, pk))
end)
end
defp pair(key, value, pk, fun) do
case fun.(value) do
{:ok, {subkey, encoded}} -> {:ok, {"#{key}.#{subkey}", encoded}}
{:ok, encoded} -> {:ok, {key(key, pk), encoded}}
:error -> :error
end
end
defp key(pk, pk), do: :_id
defp key(key, _), do: key
defp map(list, fun) do
return =
Enum.flat_map_reduce(list, :ok, fn elem, :ok ->
case fun.(elem) do
{:ok, value} -> {[value], :ok}
:error -> {:halt, :error}
end
end)
case return do
{values, :ok} -> {:ok, values}
{_values, :error} -> :error
end
end
end