11defmodule CodeCorpsWeb.Plug.DataToAttributes do
22 @ moduledoc ~S"""
3- Converts params in the JSON api "data" format into flat params convient for
3+ Converts params in the JSON api format into flat params convient for
44 changeset casting.
55
6- This is done using `JaSerializer.Params.to_attributes/1`
6+ For base parameters, this is done using `JaSerializer.Params.to_attributes/1`
7+
8+ For included records, this is done using custom code.
79 """
810
911 alias Plug.Conn
@@ -12,13 +14,38 @@ defmodule CodeCorpsWeb.Plug.DataToAttributes do
1214 def init ( opts ) , do: opts
1315
1416 @ spec call ( Conn . t , Keyword . t ) :: Plug.Conn . t
15- def call ( % Conn { params: % { "data" => data } = params } = conn , _opts ) do
17+ def call ( % Conn { params: % { } = params } = conn , opts \\ [ ] ) do
1618 attributes =
1719 params
1820 |> Map . delete ( "data" )
19- |> Map . merge ( data |> JaSerializer.Params . to_attributes )
21+ |> Map . delete ( "included" )
22+ |> Map . merge ( params |> parse_data ( ) )
23+ |> Map . merge ( params |> parse_included ( opts ) )
2024
2125 conn |> Map . put ( :params , attributes )
2226 end
23- def call ( % Conn { } = conn , _opts ) , do: conn
27+
28+ @ spec parse_data ( map ) :: map
29+ defp parse_data ( % { "data" => data } ) , do: data |> JaSerializer.Params . to_attributes
30+ defp parse_data ( % { } ) , do: % { }
31+
32+ @ spec parse_included ( map , Keyword . t ) :: map
33+ defp parse_included ( % { "included" => included } , opts ) do
34+ included |> Enum . reduce ( % { } , fn ( % { "data" => % { "type" => type } } = params , parsed ) ->
35+ attributes = params |> parse_data ( )
36+
37+ if opts |> Keyword . get ( :includes_many , [ ] ) |> Enum . member? ( type ) do
38+ # this is an explicitly specified has_many,
39+ # update existing data by adding new record
40+ pluralized_type = type |> Inflex . pluralize
41+ parsed |> Map . update ( pluralized_type , [ attributes ] , fn data ->
42+ data ++ [ attributes ]
43+ end )
44+ else
45+ # this is a belongs to, put a new submap into payload
46+ parsed |> Map . put ( type , attributes )
47+ end
48+ end )
49+ end
50+ defp parse_included ( % { } , _opts ) , do: % { }
2451end
0 commit comments