Skip to content

Commit

Permalink
mix format + more docs #2
Browse files Browse the repository at this point in the history
  • Loading branch information
nelsonic committed Oct 4, 2020
1 parent 84140f2 commit 94eea74
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 26 deletions.
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,12 @@ iex> Useful.flatten_map(map)
```

**Note**: `flatten_map/1` converts all Map keys to `Atom`
as it's easier to work with atoms as keys e.g: `person.name` instead of `person["name"]`.
We use the `__` (_double underscore_) as the delimiter for the keys of nested maps,
because if we attempt to use `.` (_period character_) we get an error:
as it's easier to work with atoms as keys
e.g: `map.person__name` instead of `map["person__name"]`.
We use the `__` (_double underscore_)
as the delimiter for the keys of nested maps,
because if we attempt to use `.` (_period character_)
we get an error:

```elixir
iex(1)> :a.b
Expand Down
20 changes: 12 additions & 8 deletions lib/useful.ex
Original file line number Diff line number Diff line change
Expand Up @@ -49,26 +49,30 @@ defmodule Useful do
|> Enum.into(%{})
end

# Recap: https://elixir-lang.org/getting-started/basic-types.html#tuples
defp to_list_of_tuples(map) do
map
|> Enum.map(&process/1)
|> List.flatten()
end

# avoids ** (Protocol.UndefinedError) protocol Enumerable
# not implemented for ~U[2016-05-24 13:26:08.003Z] of type DateTime
defp process({key, %Date{} = date}), do: return({key, date})
defp process({key, %DateTime{} = datetime}), do: return({key, datetime})
# avoids the error "** (Protocol.UndefinedError) protocol Enumerable
# not implemented for ~U[2017-08-05 16:34:08.003Z] of type DateTime"
defp process({key, %Date{} = date}), do: format({key, date})
defp process({key, %DateTime{} = datetime}), do: format({key, datetime})

# process nested maps
defp process({key, sub_map}) when is_map(sub_map) do
for {sub_key, value} <- flatten_map(sub_map) do
{String.to_atom("#{key}__#{sub_key}"), value}
format({"#{key}__#{sub_key}", value})
end
end

defp process({key, value}), do: return({key, value})
# defp process(value), do: value
defp return({key, value}) do
# catch-all for any type of key/value
defp process({key, value}), do: format({key, value})

# format the {key: value} with Atom key for simpler access
defp format({key, value}) do
{String.to_atom("#{key}"), value}
end
end
35 changes: 20 additions & 15 deletions test/useful_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ defmodule UsefulTest do
end

test "atomize_map_keys/1 converts deeply nested map" do
map = %{"name" => "alex", id: 1, nested: %{ "age" => 17, height: 185}}
map = %{"name" => "alex", id: 1, nested: %{"age" => 17, height: 185}}
# IO.inspect(map, label: "map")
expected = Useful.atomize_map_keys(map)
assert expected == %{id: 1, name: "alex", nested: %{age: 17, height: 185}}
Expand All @@ -23,17 +23,20 @@ defmodule UsefulTest do

test "flatten_map/1 handles Date and DateTime values" do
map = %{
date: Date.from_erl!({2000, 1, 1}),
date: Date.from_erl!({1999, 2, 14}),
data: %{
dateTime: DateTime.from_naive!(~N[2016-05-24 13:26:08.003], "Etc/UTC"),
height: 185}
dateTime: DateTime.from_naive!(~N[2017-08-05 16:34:08.003], "Etc/UTC"),
height: 185
}
}

expected = Useful.flatten_map(map)

assert expected == %{
data__dateTime: ~U[2016-05-24 13:26:08.003Z],
data__height: 185,
date: ~D[2000-01-01]
}
data__dateTime: ~U[2017-08-05 16:34:08.003Z],
data__height: 185,
date: ~D[1999-02-14]
}
end

test "flatten super nested map" do
Expand All @@ -52,13 +55,15 @@ defmodule UsefulTest do
}
}
}

expected = Useful.flatten_map(map)

assert expected == %{
data__address__detail__house_color: "white",
data__address__detail__more_info__architect: "James Hoban",
data__address__first_line: "1600 Pennsylvania Avenue",
data__address__post_code: "20500",
name: "Alex"
}
data__address__detail__house_color: "white",
data__address__detail__more_info__architect: "James Hoban",
data__address__first_line: "1600 Pennsylvania Avenue",
data__address__post_code: "20500",
name: "Alex"
}
end
end
end

0 comments on commit 94eea74

Please sign in to comment.