@@ -458,7 +458,7 @@ defmodule AshJsonApi.Controllers.Helpers do
458458 def add_to_relationship ( request , relationship_name ) do
459459 chain ( request , fn % { assigns: % { result: result } } ->
460460 action = Ash.Resource.Info . primary_action! ( request . resource , :update ) . name
461- values = normalize_relationship_identifiers ( request )
461+ values = relationship_change_values ( request , relationship_name )
462462
463463 result
464464 |> Ash.Changeset . new ( )
@@ -469,8 +469,24 @@ defmodule AshJsonApi.Controllers.Helpers do
469469 |> Ash . update ( Request . opts ( request ) )
470470 |> case do
471471 { :ok , updated } ->
472+ identifier_meta =
473+ case request . resource_identifiers do
474+ list when is_list ( list ) ->
475+ Enum . reduce ( list , % { } , fn
476+ { % { id: id } , meta } , acc when is_map ( meta ) ->
477+ Map . put ( acc , id , meta )
478+
479+ _ , acc ->
480+ acc
481+ end )
482+
483+ _ ->
484+ % { }
485+ end
486+
472487 request
473488 |> Request . assign ( :result , Map . get ( updated , relationship_name ) )
489+ |> Request . assign ( :relationship_identifier_meta , identifier_meta )
474490
475491 { :error , error } ->
476492 Request . add_error ( request , error , :add_to_relationship )
@@ -481,7 +497,7 @@ defmodule AshJsonApi.Controllers.Helpers do
481497 def replace_relationship ( request , relationship_name ) do
482498 chain ( request , fn % { assigns: % { result: result } } ->
483499 action = Ash.Resource.Info . primary_action! ( request . resource , :update ) . name
484- values = normalize_relationship_identifiers ( request )
500+ values = relationship_change_values ( request , relationship_name )
485501
486502 result
487503 |> Ash.Changeset . new ( )
@@ -504,7 +520,7 @@ defmodule AshJsonApi.Controllers.Helpers do
504520 def delete_from_relationship ( request , relationship_name ) do
505521 chain ( request , fn % { assigns: % { result: result } } ->
506522 action = Ash.Resource.Info . primary_action! ( request . resource , :update ) . name
507- values = normalize_relationship_identifiers ( request )
523+ values = relationship_change_values ( request , relationship_name )
508524
509525 result
510526 |> Ash.Changeset . new ( )
@@ -1089,4 +1105,45 @@ defmodule AshJsonApi.Controllers.Helpers do
10891105 id
10901106 end
10911107 end
1108+
1109+ defp relationship_change_values ( request , relationship_name ) do
1110+ relationship = Ash.Resource.Info . relationship ( request . resource , relationship_name )
1111+
1112+ meta_mapping =
1113+ AshJsonApi.Resource.Info . relationship_meta_mapping ( request . resource , relationship_name )
1114+
1115+ if match? ( % Ash.Resource.Relationships.ManyToMany { } , relationship ) and meta_mapping != [ ] do
1116+ build_many_to_many_values ( request . resource_identifiers , relationship , meta_mapping )
1117+ else
1118+ normalize_relationship_identifiers ( request )
1119+ end
1120+ end
1121+
1122+ defp build_many_to_many_values ( nil , _relationship , _meta_mapping ) , do: nil
1123+
1124+ defp build_many_to_many_values ( list , relationship , meta_mapping ) when is_list ( list ) do
1125+ destination_field = relationship . destination_attribute
1126+
1127+ Enum . map ( list , fn
1128+ { % { id: id } , meta } ->
1129+ attrs =
1130+ Enum . reduce ( meta_mapping , % { } , fn { meta_key , join_attr } , acc ->
1131+ case Map . fetch ( meta , to_string ( meta_key ) ) do
1132+ { :ok , value } -> Map . put ( acc , join_attr , value )
1133+ :error -> acc
1134+ end
1135+ end )
1136+
1137+ if map_size ( attrs ) == 0 do
1138+ id
1139+ else
1140+ Map . put ( attrs , destination_field , id )
1141+ end
1142+
1143+ % { id: id } ->
1144+ id
1145+ end )
1146+ end
1147+
1148+ defp build_many_to_many_values ( % { id: id } , _relationship , _meta_mapping ) , do: id
10921149end
0 commit comments