Skip to content

Commit fdf5b9a

Browse files
committed
Remove aalang files and update JSON handling
1 parent 08238e4 commit fdf5b9a

5 files changed

Lines changed: 117 additions & 45 deletions

File tree

lib/ash_json_api/controllers/helpers.ex

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +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+
relationship = Ash.Resource.Info.relationship(request.resource, relationship_name)
461462
values = relationship_change_values(request, relationship_name)
462463

463464
result
@@ -469,24 +470,15 @@ defmodule AshJsonApi.Controllers.Helpers do
469470
|> Ash.update(Request.opts(request))
470471
|> case do
471472
{: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
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)
486478

487-
request
488-
|> Request.assign(:result, Map.get(updated, relationship_name))
489-
|> Request.assign(:relationship_identifier_meta, identifier_meta)
479+
{:error, error} ->
480+
Request.add_error(request, error, :add_to_relationship)
481+
end
490482

491483
{:error, error} ->
492484
Request.add_error(request, error, :add_to_relationship)
@@ -497,6 +489,7 @@ defmodule AshJsonApi.Controllers.Helpers do
497489
def replace_relationship(request, relationship_name) do
498490
chain(request, fn %{assigns: %{result: result}} ->
499491
action = Ash.Resource.Info.primary_action!(request.resource, :update).name
492+
relationship = Ash.Resource.Info.relationship(request.resource, relationship_name)
500493
values = relationship_change_values(request, relationship_name)
501494

502495
result
@@ -508,8 +501,15 @@ defmodule AshJsonApi.Controllers.Helpers do
508501
|> Ash.update(Request.opts(request))
509502
|> case do
510503
{:ok, updated} ->
511-
request
512-
|> 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
513513

514514
{:error, error} ->
515515
Request.add_error(request, error, :replace_relationship)
@@ -520,6 +520,7 @@ defmodule AshJsonApi.Controllers.Helpers do
520520
def delete_from_relationship(request, relationship_name) do
521521
chain(request, fn %{assigns: %{result: result}} ->
522522
action = Ash.Resource.Info.primary_action!(request.resource, :update).name
523+
relationship = Ash.Resource.Info.relationship(request.resource, relationship_name)
523524
values = relationship_change_values(request, relationship_name)
524525

525526
result
@@ -534,8 +535,15 @@ defmodule AshJsonApi.Controllers.Helpers do
534535
|> Ash.load(fields(request, request.resource), Request.load_opts(request))
535536
|> case do
536537
{:ok, updated} ->
537-
request
538-
|> 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
539547

540548
{:error, error} ->
541549
Request.add_error(request, error, :delete_from_relationship)
@@ -1110,7 +1118,7 @@ defmodule AshJsonApi.Controllers.Helpers do
11101118
relationship = Ash.Resource.Info.relationship(request.resource, relationship_name)
11111119

11121120
meta_mapping =
1113-
AshJsonApi.Resource.Info.relationship_meta_mapping(request.resource, relationship_name)
1121+
AshJsonApi.Resource.Info.relationship_meta_in_mapping(request.resource, relationship_name)
11141122

11151123
if match?(%Ash.Resource.Relationships.ManyToMany{}, relationship) and meta_mapping != [] do
11161124
build_many_to_many_values(request.resource_identifiers, relationship, meta_mapping)
@@ -1146,4 +1154,14 @@ defmodule AshJsonApi.Controllers.Helpers do
11461154
end
11471155

11481156
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
11491167
end

lib/ash_json_api/resource/info.ex

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,56 @@ defmodule AshJsonApi.Resource.Info do
8080
Extension.get_opt(resource, [:json_api], :relationship_meta, [], true)
8181
end
8282

83+
@doc """
84+
Returns the `relationship_meta_in` config for the resource.
85+
Falls back to `relationship_meta` when not set.
86+
"""
87+
def relationship_meta_in(resource) do
88+
Extension.get_opt(
89+
resource,
90+
[:json_api],
91+
:relationship_meta_in,
92+
relationship_meta(resource),
93+
true
94+
)
95+
end
96+
97+
@doc """
98+
Returns the `relationship_meta_out` config for the resource.
99+
Falls back to `relationship_meta` when not set.
100+
"""
101+
def relationship_meta_out(resource) do
102+
Extension.get_opt(
103+
resource,
104+
[:json_api],
105+
:relationship_meta_out,
106+
relationship_meta(resource),
107+
true
108+
)
109+
end
110+
111+
@doc """
112+
Returns the incoming meta-to-join-attribute mapping for the given relationship name.
113+
"""
114+
def relationship_meta_in_mapping(resource, relationship_name) do
115+
relationship_meta_in(resource)[relationship_name] || []
116+
end
117+
118+
@doc """
119+
Returns the outgoing meta-to-join-attribute mapping for the given relationship name.
120+
"""
121+
def relationship_meta_out_mapping(resource, relationship_name) do
122+
relationship_meta_out(resource)[relationship_name] || []
123+
end
124+
83125
@doc """
84126
Returns the meta-to-join-attribute mapping for the given relationship name.
85127
86128
The result is a keyword list like `[note: :note_on_join]`, where the key is the
87129
JSON:API meta key (as an atom) and the value is the join resource attribute.
88130
"""
89131
def relationship_meta_mapping(resource, relationship_name) do
90-
relationship_meta(resource)[relationship_name] || []
132+
relationship_meta_in_mapping(resource, relationship_name)
91133
end
92134

93135
defp camelize(name) do

lib/ash_json_api/resource/resource.ex

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -561,7 +561,10 @@ defmodule AshJsonApi.Resource do
561561
type: :keyword_list,
562562
default: [],
563563
doc: """
564-
Configures how join-table fields are exposed via JSON:API `meta` on relationship
564+
Backward-compatible shorthand for setting both `relationship_meta_in` and
565+
`relationship_meta_out` to the same mapping.
566+
567+
Configures how join-table fields are mapped via JSON:API `meta` on relationship
565568
resource identifiers for many_to_many relationships.
566569
567570
The value is a keyword list keyed by relationship name, where each value is
@@ -578,6 +581,22 @@ defmodule AshJsonApi.Resource do
578581
on relationship resource identifiers for that relationship.
579582
"""
580583
],
584+
relationship_meta_in: [
585+
type: :keyword_list,
586+
default: [],
587+
doc: """
588+
Configures how incoming JSON:API `meta` keys on relationship resource identifiers
589+
map to join resource attributes for many_to_many relationship writes.
590+
"""
591+
],
592+
relationship_meta_out: [
593+
type: :keyword_list,
594+
default: [],
595+
doc: """
596+
Configures how join resource attributes map to outgoing JSON:API `meta` keys on
597+
relationship resource identifiers for many_to_many relationship reads.
598+
"""
599+
],
581600
field_names: [
582601
type: {:or, [{:literal, :camelize}, {:literal, :dasherize}, :keyword_list, {:fun, 1}]},
583602
doc: """

lib/ash_json_api/serializer.ex

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,13 @@ defmodule AshJsonApi.Serializer do
1212
%{self: at_host(request, request.url)}
1313
|> add_related_link(request, source_record, relationship)
1414

15-
identifier_meta =
16-
Map.get(request.assigns, :relationship_identifier_meta, %{})
17-
1815
%{
1916
links: links,
2017
data:
21-
Enum.map(List.wrap(records), fn record ->
22-
payload = serialize_relationship_data(record, source_record, relationship)
23-
24-
case Map.fetch(identifier_meta, AshJsonApi.Resource.encode_primary_key(record)) do
25-
{:ok, meta_for_identifier} when is_map(meta_for_identifier) and
26-
map_size(meta_for_identifier) > 0 ->
27-
Map.put(payload, :meta, meta_for_identifier)
28-
29-
_ ->
30-
payload
31-
end
32-
end),
18+
Enum.map(
19+
List.wrap(records),
20+
&serialize_relationship_data(&1, source_record, relationship)
21+
),
3322
meta: meta
3423
}
3524
|> Jason.encode!()
@@ -182,7 +171,7 @@ defmodule AshJsonApi.Serializer do
182171
source_resource = source_record.__struct__
183172

184173
meta_mapping =
185-
AshJsonApi.Resource.Info.relationship_meta_mapping(source_resource, relationship.name)
174+
AshJsonApi.Resource.Info.relationship_meta_out_mapping(source_resource, relationship.name)
186175

187176
if meta_mapping == [] do
188177
payload

test/acceptance/relationships_test.exs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,9 @@ defmodule AshJsonApi.Acceptance.RelationshipsTest do
8787
json_api do
8888
type("person")
8989

90-
relationship_meta [
91-
tags: [note: :note]
92-
]
90+
relationship_meta_in(tags: [note: :note])
91+
92+
relationship_meta_out(tags: [note_out: :note])
9393

9494
routes do
9595
base("/people")
@@ -209,7 +209,7 @@ defmodule AshJsonApi.Acceptance.RelationshipsTest do
209209

210210
body = %{
211211
"data" => [
212-
%{"type" => "tag", "id" => tag.id, "meta" => %{"note" => "any"}}
212+
%{"type" => "tag", "id" => tag.id, "meta" => %{"note" => "any", "ignored" => "value"}}
213213
]
214214
}
215215

@@ -229,12 +229,16 @@ defmodule AshJsonApi.Acceptance.RelationshipsTest do
229229
%{
230230
"id" => id,
231231
"type" => "tag",
232-
"meta" => %{"note" => "any"}
232+
"meta" => meta
233233
}
234234
]
235235
} = response.resp_body
236236

237237
assert id == tag.id
238+
assert Map.has_key?(meta, "note_out")
239+
refute Map.get(meta, "note_out") == "any"
240+
refute Map.has_key?(meta, "ignored")
241+
refute Map.has_key?(meta, "note")
238242
end
239243

240244
test "post_to_relationship accepts multiple identifiers" do

0 commit comments

Comments
 (0)