defmodule Ash.Resource.Transformers.CreateJoinRelationship do
@moduledoc """
Creates an automatically named `has_many` relationship for each many_to_many.
This will likely not be around for long, as our logic around many to many relationships
will update soon.
"""
use Spark.Dsl.Transformer
alias Spark.Dsl.Transformer
@extension Ash.Resource.Dsl
def transform(dsl_state) do
dsl_state
|> Transformer.get_entities([:relationships])
|> Enum.filter(&(&1.type == :many_to_many))
|> Enum.reject(fn relationship ->
dsl_state
|> Transformer.get_entities([:relationships])
|> Enum.find(&(&1.name == relationship.join_relationship))
end)
|> Enum.reduce({:ok, dsl_state}, fn relationship, {:ok, dsl_state} ->
autogenerated_join_relationship_of = relationship.name
{:ok, relationship} =
Transformer.build_entity(
@extension,
[:relationships],
:has_many,
[
name: relationship.join_relationship,
destination: relationship.through,
destination_attribute: relationship.source_attribute_on_join_resource,
api: relationship.api,
source_attribute: relationship.source_attribute,
private?: true
]
|> add_messages(relationship)
)
relationship =
Map.put(
relationship,
:autogenerated_join_relationship_of,
autogenerated_join_relationship_of
)
{:ok, Transformer.add_entity(dsl_state, [:relationships], relationship)}
end)
end
defp add_messages(opts, relationship) do
new_opts =
[
not_found_message: relationship.not_found_message,
violation_message: relationship.violation_message
]
|> Enum.reject(fn {_, v} ->
is_nil(v)
end)
Keyword.merge(opts, new_opts)
end
def before?(Ash.Resource.Transformers.SetRelationshipSource), do: true
def before?(_), do: false
end