UndefinedFunctionError when using map(:string) field type
Contract taken from the README (and slimmed down):
defmodule UserContract do
use Drops.Contract
schema do
%{
required(:name) => string(),
optional(:settings) => map(:string),
required(:address) => maybe(:string)
}
end
end
Trying to conform a map with settings results in an unmanaged UndefinedFunctionError exception:
UserContract.conform(%{name: "Jane", settings: %{"theme" => "dark"}, address: "main road 1"})
** (UndefinedFunctionError) function Drops.Predicates.string/1 is undefined or private
(drops 0.2.0) Drops.Predicates.string(%{"theme" => "dark"})
(drops 0.2.0) lib/drops/predicates/helpers.ex:22: Drops.Predicates.Helpers.apply_predicate/2
(elixir 1.17.1) lib/enum.ex:2531: Enum."-reduce/3-lists^foldl/2-0-"/3
(drops 0.2.0) lib/drops/types/map/key.ex:15: Drops.Types.Map.Key.validate/2
(elixir 1.17.1) lib/enum.ex:1703: Enum."-map/2-lists^map/1-1-"/2
(drops 0.2.0) lib/drops/types/map.ex:63: Drops.Types.Map.Validator.validate/2
#cell:rziepynrh7l5vn3j:2: UserContract.conform/3
#cell:7x24e72nc24vkawk:1: (file)
No issue if we remove the settings key from the map:
UserContract.conform(%{name: "Jane", address: "main road 1"})
# {:ok, %{name: "Jane", address: "main road 1"}}
Is it a bug with the library, or an incorrect/outdated README/documentation? If the latter, what's the proper way to have a field that needs to be a map with string values?
Thanks for reporting this - it is not yet supported, but will be eventually. We could have a syntax like that for this:
map(keys: any(), values: string())
# or
map(%{ any() => string() })
WDYT?
Personally, I like the first syntax. map(%{any() => string()}) makes me think of a map of maps; and also the keyword list syntax is more readable and would allow for more options and defaults.