@@ -458,7 +458,8 @@ 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+ relationship = Ash.Resource.Info . relationship ( request . resource , relationship_name )
462+ values = relationship_change_values ( request , relationship_name )
462463
463464 result
464465 |> Ash.Changeset . new ( )
@@ -469,8 +470,15 @@ defmodule AshJsonApi.Controllers.Helpers do
469470 |> Ash . update ( Request . opts ( request ) )
470471 |> case do
471472 { :ok , updated } ->
472- request
473- |> Request . assign ( :result , Map . get ( updated , relationship_name ) )
473+ case load_result_for_relationship_meta ( updated , relationship , request ) do
474+ { :ok , updated_with_join_rows } ->
475+ request
476+ |> Request . assign ( :result , Map . get ( updated_with_join_rows , relationship_name ) )
477+ |> Request . assign ( :record_from_path , updated_with_join_rows )
478+
479+ { :error , error } ->
480+ Request . add_error ( request , error , :add_to_relationship )
481+ end
474482
475483 { :error , error } ->
476484 Request . add_error ( request , error , :add_to_relationship )
@@ -481,7 +489,8 @@ defmodule AshJsonApi.Controllers.Helpers do
481489 def replace_relationship ( request , relationship_name ) do
482490 chain ( request , fn % { assigns: % { result: result } } ->
483491 action = Ash.Resource.Info . primary_action! ( request . resource , :update ) . name
484- values = normalize_relationship_identifiers ( request )
492+ relationship = Ash.Resource.Info . relationship ( request . resource , relationship_name )
493+ values = relationship_change_values ( request , relationship_name )
485494
486495 result
487496 |> Ash.Changeset . new ( )
@@ -492,8 +501,15 @@ defmodule AshJsonApi.Controllers.Helpers do
492501 |> Ash . update ( Request . opts ( request ) )
493502 |> case do
494503 { :ok , updated } ->
495- request
496- |> Request . assign ( :result , Map . get ( updated , relationship_name ) )
504+ case load_result_for_relationship_meta ( updated , relationship , request ) do
505+ { :ok , updated_with_join_rows } ->
506+ request
507+ |> Request . assign ( :result , Map . get ( updated_with_join_rows , relationship_name ) )
508+ |> Request . assign ( :record_from_path , updated_with_join_rows )
509+
510+ { :error , error } ->
511+ Request . add_error ( request , error , :replace_relationship )
512+ end
497513
498514 { :error , error } ->
499515 Request . add_error ( request , error , :replace_relationship )
@@ -504,7 +520,8 @@ 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+ relationship = Ash.Resource.Info . relationship ( request . resource , relationship_name )
524+ values = relationship_change_values ( request , relationship_name )
508525
509526 result
510527 |> Ash.Changeset . new ( )
@@ -518,8 +535,15 @@ defmodule AshJsonApi.Controllers.Helpers do
518535 |> Ash . load ( fields ( request , request . resource ) , Request . load_opts ( request ) )
519536 |> case do
520537 { :ok , updated } ->
521- request
522- |> Request . assign ( :result , Map . get ( updated , relationship_name ) )
538+ case load_result_for_relationship_meta ( updated , relationship , request ) do
539+ { :ok , updated_with_join_rows } ->
540+ request
541+ |> Request . assign ( :result , Map . get ( updated_with_join_rows , relationship_name ) )
542+ |> Request . assign ( :record_from_path , updated_with_join_rows )
543+
544+ { :error , error } ->
545+ Request . add_error ( request , error , :delete_from_relationship )
546+ end
523547
524548 { :error , error } ->
525549 Request . add_error ( request , error , :delete_from_relationship )
@@ -1089,4 +1113,55 @@ defmodule AshJsonApi.Controllers.Helpers do
10891113 id
10901114 end
10911115 end
1116+
1117+ defp relationship_change_values ( request , relationship_name ) do
1118+ relationship = Ash.Resource.Info . relationship ( request . resource , relationship_name )
1119+
1120+ meta_mapping =
1121+ AshJsonApi.Resource.Info . relationship_meta_in_mapping ( request . resource , relationship_name )
1122+
1123+ if match? ( % Ash.Resource.Relationships.ManyToMany { } , relationship ) and meta_mapping != [ ] do
1124+ build_many_to_many_values ( request . resource_identifiers , relationship , meta_mapping )
1125+ else
1126+ normalize_relationship_identifiers ( request )
1127+ end
1128+ end
1129+
1130+ defp build_many_to_many_values ( nil , _relationship , _meta_mapping ) , do: nil
1131+
1132+ defp build_many_to_many_values ( list , relationship , meta_mapping ) when is_list ( list ) do
1133+ destination_field = relationship . destination_attribute
1134+
1135+ Enum . map ( list , fn
1136+ { % { id: id } , meta } ->
1137+ attrs =
1138+ Enum . reduce ( meta_mapping , % { } , fn { meta_key , join_attr } , acc ->
1139+ case Map . fetch ( meta , to_string ( meta_key ) ) do
1140+ { :ok , value } -> Map . put ( acc , join_attr , value )
1141+ :error -> acc
1142+ end
1143+ end )
1144+
1145+ if map_size ( attrs ) == 0 do
1146+ id
1147+ else
1148+ Map . put ( attrs , destination_field , id )
1149+ end
1150+
1151+ % { id: id } ->
1152+ id
1153+ end )
1154+ end
1155+
1156+ defp build_many_to_many_values ( % { id: id } , _relationship , _meta_mapping ) , do: id
1157+
1158+ defp load_result_for_relationship_meta ( updated , relationship , request ) do
1159+ case relationship do
1160+ % Ash.Resource.Relationships.ManyToMany { join_relationship: join_relationship } ->
1161+ Ash . load ( updated , [ join_relationship ] , Request . load_opts ( request ) )
1162+
1163+ _ ->
1164+ { :ok , updated }
1165+ end
1166+ end
10921167end
0 commit comments