Skip to content

Commit

Permalink
Add Mayo.Map module
Browse files Browse the repository at this point in the history
  • Loading branch information
tommy351 committed Jul 3, 2016
1 parent ba9cd86 commit e963546
Show file tree
Hide file tree
Showing 5 changed files with 190 additions and 6 deletions.
4 changes: 2 additions & 2 deletions lib/mayo.ex
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ defmodule Mayo do
end

defp reduce_map_pipes({key, pipes}, acc) do
item = quote do: Access.get(result, unquote(key))
item = quote do: Mayo.Access.get(result, unquote(key))
pipe = compile(pipes, item)

quote do
Expand All @@ -65,7 +65,7 @@ defmodule Mayo do
{:error, %{err | paths: [unquote(key) | paths]}}

value ->
Access.put(result, unquote(key), value)
Mayo.Access.put(result, unquote(key), value)
end
end
end
Expand Down
33 changes: 33 additions & 0 deletions lib/mayo/access.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
defmodule Mayo.Access do
def fetch(value, key) when is_map(value) do
Map.fetch(value, key)
end

def fetch(value, key) when is_list(value) do
Keyword.fetch(value, key)
end

def get(value, key) when is_map(value) do
Map.get(value, key)
end

def get(value, key) when is_list(value) do
Keyword.get(value, key)
end

def put(value, key, new) when is_map(value) do
Map.put(value, key, new)
end

def put(value, key, new) when is_list(value) do
Keyword.put(value, key, new)
end

def delete(value, key) when is_map(value) do
Map.delete(value, key)
end

def delete(value, key) when is_list(value) do
Keyword.delete(value, key)
end
end
143 changes: 143 additions & 0 deletions lib/mayo/map.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
defmodule Mayo.Map do
@doc """
Checks the minimum number of the keys in the map.
iex> Mayo.Map.min(%{foo: "bar"}, 1)
%{foo: "bar"}
iex> Mayo.Map.min(%{}, 1)
{:error, %Mayo.Error{type: "map.min"}}
"""
def min(value, len) when is_map(value) do
if length(Map.keys(value)) < len do
{:error, %Mayo.Error{
type: "map.min"
}}
else
value
end
end

def min(value, _), do: value

@doc """
Checks the maximum number of the keys in the map.
iex> Mayo.Map.max(%{foo: "bar"}, 1)
%{foo: "bar"}
iex> Mayo.Map.max(%{foo: "bar", baz: "boo"}, 1)
{:error, %Mayo.Error{type: "map.max"}}
"""
def max(value, len) when is_map(value) do
if length(Map.keys(value)) > len do
{:error, %Mayo.Error{
type: "map.max"
}}
else
value
end
end

def max(value, _), do: value

@doc """
Checks the number of the keys in the map.
iex> Mayo.Map.length(%{foo: "bar"}, 1)
%{foo: "bar"}
iex> Mayo.Map.length(%{}, 1)
{:error, %Mayo.Error{type: "map.length"}}
"""
def length(value, len) when is_map(value) do
if length(Map.keys(value)) == len do
value
else
{:error, %Mayo.Error{
type: "map.length"
}}
end
end

def length(value, _), do: value

@doc """
Checks the presence of keys.
iex> Mayo.Map.with(%{foo: "bar", baz: "boo"}, [:foo, :baz])
%{foo: "bar", baz: "boo"}
iex> Mayo.Map.with(%{foo: "bar"}, [:foo, :baz])
{:error, %Mayo.Error{type: "map.with", paths: [:baz]}}
"""
def with(value, peers) when is_map(value) do
Enum.reduce peers, value, fn key, acc ->
case acc do
{:error, _} = err -> err

_ ->
case Map.fetch(acc, key) do
:error -> {:error, %Mayo.Error{
paths: [key],
type: "map.with"
}}

_ -> acc
end
end
end
end

def with(value, _), do: value

@doc """
Forbids the presence of keys.
iex> Mayo.Map.without(%{foo: "bar"}, [:baz, :boo])
%{foo: "bar"}
iex> Mayo.Map.without(%{foo: "bar", baz: "boo"}, [:baz, :boo])
{:error, %Mayo.Error{type: "map.without", paths: [:baz]}}
"""
def without(value, peers) when is_map(value) do
Enum.reduce peers, value, fn key, acc ->
case acc do
{:error, _} = err -> err

_ ->
case Map.fetch(acc, key) do
:error -> acc

_ -> {:error, %Mayo.Error{
paths: [key],
type: "map.without"
}}
end
end
end
end

def without(value, _), do: value

@doc """
Rename a key to another name.
iex> Mayo.Map.rename(%{foo: "bar"}, :foo, :baz)
%{baz: "bar"}
iex> Mayo.Map.rename(%{foo: "bar"}, :bar, :baz)
%{foo: "bar"}
"""
def rename(value, from, to) when is_map(value) do
case Map.fetch(value, from) do
{:ok, result} ->
Map.put(value, to, result)
|> Map.delete(from)

:error -> value
end
end

def rename(value, _, _), do: value
end
4 changes: 4 additions & 0 deletions test/mayo/map_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
defmodule Mayo.MapTest do
use ExUnit.Case
doctest Mayo.Map
end
12 changes: 8 additions & 4 deletions test/mayo_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ defmodule MayoTest do
doctest Mayo

test "map" do
result = Mayo.validate %{}, %{
result = Mayo.validate %{
username: "test"
}, %{
username: Mayo.Any.string |> Mayo.String.min(4)
}

assert result == %{}
assert result == %{username: "test"}

result = Mayo.validate %{}, %{
username: Mayo.Any.string |> Mayo.Any.required |> Mayo.String.min(4)
Expand All @@ -31,11 +33,13 @@ defmodule MayoTest do
end

test "keyword list" do
result = Mayo.validate [], [
result = Mayo.validate [
username: "test"
], [
username: Mayo.Any.string |> Mayo.String.min(4)
]

assert result == []
assert result == [username: "test"]

result = Mayo.validate [], [
username: Mayo.Any.string |> Mayo.Any.required |> Mayo.String.min(4)
Expand Down

0 comments on commit e963546

Please sign in to comment.