Skip to content

Commit

Permalink
Feat/enumerable (#63)
Browse files Browse the repository at this point in the history
* add enumerable util

* fix type spec of the do_split function.

* fix code format

* improve docs and tests

* improve docs

* fix README
  • Loading branch information
elielhaouzi authored and sobolevn committed Jul 8, 2019
1 parent c076d75 commit e161a1a
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 1 deletion.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,17 @@ Recase.to_title("some-value") # => "Some Value"
Recase.to_title("some value") # => "Some Value"
```

### Enumerable

You can convert all keys in an enumerable with:

```elixir
Recase.Enumerable.convert_keys(%{"yourKey" => "value"}, &Recase.to_snake/1) # => %{"your_key" => "value"}
Recase.Enumerable.convert_keys(%{"your_key" => "value"}, &Recase.to_camel/1) # => %{"yourKey" => "value"}
Recase.Enumerable.convert_keys(%{"your_key" => %{"yourKey" => "value"}}, &Recase.to_pascal/1) # => %{"YourKey" => %{"YourKey" => "value"}}
Recase.Enumerable.convert_keys([%{"yourKey" => "value"}], &Recase.to_snake/1) # => [%{"your_key" => "value"}]
```

## Changelog

Full changelog is available [here](https://github.com/sobolevn/recase/blob/master/CHANGELOG.md).
Expand Down
4 changes: 3 additions & 1 deletion lib/recase/cases/generic.ex
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ defmodule Recase.Generic do

##############################################################################

@spec do_split(input :: String.t(), acc :: [String.t()]) :: [String.t()]
@spec do_split(input :: String.t(), {binary(), acc :: [String.t()]}) :: [
String.t()
]
defp do_split(string, acc \\ {"", []})

defp do_split("", {"", acc}), do: Enum.reverse(acc)
Expand Down
27 changes: 27 additions & 0 deletions lib/recase/utils/enumerable.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
defmodule Recase.Enumerable do
@moduledoc """
Helper module to convert enumerable keys recursively.
"""

@doc """
Invoke fun for each keys of the enumerable.
"""
@spec convert_keys(Enumerable.t(), fun) :: Enumerable.t()
def convert_keys(enumerable, fun) when is_map(enumerable) do
enumerable
|> Enum.into(%{}, fn {key, value} ->
{fun.(key), handle_value(value, fun)}
end)
end

def convert_keys(enumerable, fun) when is_list(enumerable) do
enumerable
|> Enum.map(&handle_value(&1, fun))
end

defp handle_value(value, fun) when is_map(value) or is_list(value) do
convert_keys(value, fun)
end

defp handle_value(value, _), do: value
end
38 changes: 38 additions & 0 deletions test/utils_test/enumerable_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
defmodule RecaseEnumerableTest do
use ExUnit.Case

test "should convert keys of a map" do
assert Recase.Enumerable.convert_keys(
%{"upper case" => "value", "upper-case2" => "value"},
&Recase.to_pascal/1
) == %{"UpperCase" => "value", "UpperCase2" => "value"}
end

test "should convert keys of a nested map" do
assert Recase.Enumerable.convert_keys(
%{"upper case" => %{"upper-case2" => "value"}},
&Recase.to_path(&1, "\\")
) == %{"upper\\case" => %{"upper\\case2" => "value"}}
end

test "should convert keys of a map in list" do
assert Recase.Enumerable.convert_keys(
[%{"upper case" => "value", "upper-case2" => "value"}],
&Recase.to_pascal/1
) == [%{"UpperCase" => "value", "UpperCase2" => "value"}]
end

test "should convert keys of a nested map in list" do
assert Recase.Enumerable.convert_keys(
[%{"upper case" => %{"upper-case2" => "value"}}],
&Recase.to_pascal/1
) == [%{"UpperCase" => %{"UpperCase2" => "value"}}]
end

test "should return the same list when list items are usual text" do
assert Recase.Enumerable.convert_keys(
["upper case", "upper-case2"],
&Recase.to_pascal/1
) == ["upper case", "upper-case2"]
end
end

0 comments on commit e161a1a

Please sign in to comment.