-
-
Notifications
You must be signed in to change notification settings - Fork 180
/
validate_relationship_attributes.ex
82 lines (71 loc) · 2.69 KB
/
validate_relationship_attributes.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
defmodule Ash.Api.Transformers.ValidateRelationshipAttributes do
@moduledoc """
Validates that all relationships point to valid fields
"""
use Ash.Dsl.Transformer
alias Ash.Dsl.Transformer
def transform(_api, dsl) do
dsl
|> Transformer.get_entities([:resources])
|> Enum.filter(& &1.warn_on_compile_failure?)
|> Enum.map(& &1.resource)
|> Enum.each(fn resource ->
attribute_names =
resource
|> Ash.Resource.Info.attributes()
|> Enum.map(& &1.name)
resource
|> Ash.Resource.Info.relationships()
|> Enum.each(&validate_relationship(&1, attribute_names))
end)
{:ok, dsl}
end
defp validate_relationship(relationship, attribute_names) do
unless relationship.source_field in attribute_names do
raise Ash.Error.Dsl.DslError,
module: __MODULE__,
path: [:relationships, relationship.name],
message:
"Relationship `#{relationship.name}` expects source field `#{relationship.source_field}` to be defined"
end
if relationship.type == :many_to_many do
through_attributes =
relationship.through
|> Ash.Resource.Info.attributes()
|> Enum.map(& &1.name)
unless relationship.source_field_on_join_table in through_attributes do
raise Ash.Error.Dsl.DslError,
module: __MODULE__,
path: [:relationships, relationship.name],
message:
"Relationship `#{relationship.name}` expects source field on join table `#{
relationship.source_field_on_join_table
}` to be defined on #{inspect(relationship.through)}"
end
unless relationship.destination_field_on_join_table in through_attributes do
raise Ash.Error.Dsl.DslError,
module: __MODULE__,
path: [:relationships, relationship.name],
message:
"Relationship `#{relationship.name}` expects destination field on join table `#{
relationship.destination_field_on_join_table
}` to be defined on #{inspect(relationship.through)}"
end
end
destination_attributes =
relationship.destination
|> Ash.Resource.Info.attributes()
|> Enum.map(& &1.name)
unless relationship.destination_field in destination_attributes do
raise Ash.Error.Dsl.DslError,
module: __MODULE__,
path: [:relationships, relationship.name],
message:
"Relationship `#{relationship.name}` expects destination field `#{
relationship.destination_field
}` to be defined on #{inspect(relationship.destination)}"
end
end
def after?(Ash.Api.Transformers.EnsureResourcesCompiled), do: true
def after?(_), do: false
end