Skip to content

Commit

Permalink
Only keep essentials in Encoder
Browse files Browse the repository at this point in the history
Move all conversions to Conversions module
  • Loading branch information
ericmj committed Dec 15, 2015
1 parent f9a44da commit ed24a5e
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 126 deletions.
18 changes: 3 additions & 15 deletions lib/mongo_ecto.ex
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,7 @@ defmodule Mongo.Ecto do
alias Mongo.Ecto.NormalizedQuery.AggregateQuery
alias Mongo.Ecto.ObjectID
alias Mongo.Ecto.Connection
alias Mongo.Ecto.Conversions

## Adapter

Expand Down Expand Up @@ -583,31 +584,18 @@ defmodule Mongo.Ecto do
end

defp process_document(document, %{fields: fields, pk: pk}, preprocess) do
document = to_ecto_pk(document, pk)
document = Conversions.to_ecto_pk(document, pk)

Enum.map(fields, fn
{:field, name, field} ->
preprocess.(field, Map.get(document, Atom.to_string(name)), nil)
{:value, value, field} ->
preprocess.(field, to_ecto_pk(value, pk), nil)
preprocess.(field, Conversions.to_ecto_pk(value, pk), nil)
field ->
preprocess.(field, document, nil)
end)
end

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

## Storage

# Noop for MongoDB, as any databases and collections are created as needed.
Expand Down
87 changes: 87 additions & 0 deletions lib/mongo_ecto/conversions.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
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),
do: {:ok, value}

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
100 changes: 0 additions & 100 deletions lib/mongo_ecto/encoder.ex

This file was deleted.

9 changes: 1 addition & 8 deletions lib/mongo_ecto/helpers.ex
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,7 @@ defmodule Mongo.Ecto.Helpers do
"""
@spec javascript(String.t, Keyword.t) :: Mongo.Ecto.JavaScript.t
def javascript(code, scope \\ []) do
case Mongo.Ecto.Encoder.encode(scope, nil) do
{:ok, []} ->
%Mongo.Ecto.JavaScript{code: code}
{:ok, scope} ->
%Mongo.Ecto.JavaScript{code: code, scope: scope}
:error ->
raise ArgumentError, "invaid expression for JavaScript scope"
end
%Mongo.Ecto.JavaScript{code: code, scope: scope}
end

@doc """
Expand Down
6 changes: 3 additions & 3 deletions lib/mongo_ecto/normalized_query.ex
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ defmodule Mongo.Ecto.NormalizedQuery do
defstruct coll: nil, pk: nil, fields: [], pipeline: [], database: nil, opts: []
end

alias Mongo.Ecto.Encoder
alias Mongo.Ecto.Conversions
alias Ecto.Query.Tagged
alias Ecto.Query

Expand Down Expand Up @@ -317,14 +317,14 @@ defmodule Mongo.Ecto.NormalizedQuery do
do: raise(Ecto.QueryError, query: query, message: message)

defp value(expr, pk, place) do
case Encoder.encode(expr, pk) do
case Conversions.from_ecto_pk(expr, pk) do
{:ok, value} -> value
:error -> error(place)
end
end

defp value(expr, params, pk, query, place) do
case Encoder.encode(expr, params, pk) do
case Conversions.inject_params(expr, params, pk) do
{:ok, value} -> value
:error -> error(query, place)
end
Expand Down

0 comments on commit ed24a5e

Please sign in to comment.