@@ -19,38 +19,60 @@ defmodule Speck.ValidationMetadata.Attribute do
1919
2020 @ doc """
2121 Merge the values from metadata attributes into a given map.
22+
23+ ## Opts
24+ - `:merge_strategy` - Determines whether a value in the params or attributes
25+ takes priority when both are present. Defaults to `:param_priority`.
2226 """
23- @ spec merge ( attributes :: [ t ] , params :: map ) :: map
24- def merge ( attributes , params ) do
27+ @ spec merge (
28+ attributes :: [ t ] ,
29+ params :: map ,
30+ opts :: [ merge_strategy: :param_priority | :attribute_priority ]
31+ ) :: map
32+ def merge ( attributes , params , opts \\ [ ] ) do
33+ merge_strategy = Keyword . get ( opts , :merge_strategy , :param_priority )
34+
2535 Enum . reduce ( attributes , params , fn { path , _status , value } , acc ->
26- merge ( acc , path , value )
36+ merge ( acc , path , value , merge_strategy )
2737 end )
2838 end
2939
30- defp merge ( nil = _params , [ path ] , value ) do
40+ defp merge ( nil = _params , [ path ] , value , _strategy ) do
3141 % { path => value }
3242 end
3343
34- defp merge ( params , [ path ] , value ) when is_map ( params ) do
35- params
36- |> to_key_strings ( )
37- |> Map . put ( path , value )
44+ defp merge ( nil = _params , [ attribute | path ] , value , strategy )
45+ when not is_integer ( attribute ) do
46+ % { attribute => merge ( % { } , path , value , strategy ) }
47+ end
48+
49+ defp merge ( params , [ path ] , value , strategy ) when is_map ( params ) do
50+ params_with_key_strings = to_key_strings ( params )
51+
52+ skip_put =
53+ strategy == :param_priority
54+ && Map . has_key? ( params_with_key_strings , path )
55+
56+ case skip_put do
57+ true -> params_with_key_strings
58+ _ -> Map . put ( params_with_key_strings , path , value )
59+ end
3860 end
3961
40- defp merge ( params , [ index | path ] , value ) when is_integer ( index ) do
62+ defp merge ( params , [ index | path ] , value , strategy ) when is_integer ( index ) do
4163 params2 = params || [ ]
4264 item = Enum . at ( params2 , index )
43- new_item = merge ( item , path , value )
65+ new_item = merge ( item , path , value , strategy )
4466
4567 case item do
4668 nil -> List . insert_at ( params2 , - 1 , new_item )
4769 _ -> List . replace_at ( params2 , index , new_item )
4870 end
4971 end
5072
51- defp merge ( params , [ attribute | path ] , value ) do
73+ defp merge ( params , [ attribute | path ] , value , strategy ) do
5274 params2 = to_key_strings ( params )
53- Map . put ( params2 , attribute , merge ( params2 [ attribute ] , path , value ) )
75+ Map . put ( params2 , attribute , merge ( params2 [ attribute ] , path , value , strategy ) )
5476 end
5577
5678 defp to_key_strings ( map ) do
0 commit comments