mirror of
https://github.com/ash-project/ash.git
synced 2024-09-20 05:23:03 +12:00
fix: join_relationship
in many to many can make through
optional (#846)
This commit is contained in:
parent
c60c5111ae
commit
91c34c3939
3 changed files with 53 additions and 31 deletions
|
@ -581,9 +581,9 @@ belongs_to :word, Word, primary_key?: true, allow_nil?: false
|
|||
|
||||
| Name | Type | Default | Docs |
|
||||
|------|------|---------|------|
|
||||
| [`through`](#relationships-many_to_many-through){: #relationships-many_to_many-through .spark-required} | `module` | | The resource to use as the join resource. |
|
||||
| [`source_attribute_on_join_resource`](#relationships-many_to_many-source_attribute_on_join_resource){: #relationships-many_to_many-source_attribute_on_join_resource } | `atom` | | The attribute on the join resource that should line up with `source_attribute` on this resource. Defaults to `<snake_cased_last_part_of_source_module_name>_id`. |
|
||||
| [`destination_attribute_on_join_resource`](#relationships-many_to_many-destination_attribute_on_join_resource){: #relationships-many_to_many-destination_attribute_on_join_resource } | `atom` | | The attribute on the join resource that should line up with `destination_attribute` on the related resource. Defaults to `<snake_cased_last_part_of_destination_module_name>_id`. |
|
||||
| [`through`](#relationships-many_to_many-through){: #relationships-many_to_many-through } | `module` | | The resource to use as the join resource. |
|
||||
| [`join_relationship`](#relationships-many_to_many-join_relationship){: #relationships-many_to_many-join_relationship } | `atom` | | The has_many relationship to the join resource. Defaults to `<relationship_name>_join_assoc`. |
|
||||
| [`description`](#relationships-many_to_many-description){: #relationships-many_to_many-description } | `String.t` | | An optional description for the relationship |
|
||||
| [`destination_attribute`](#relationships-many_to_many-destination_attribute){: #relationships-many_to_many-destination_attribute } | `atom` | `:id` | The attribute on the related resource that should match the `source_attribute` configured on this resource. |
|
||||
|
|
|
@ -58,19 +58,16 @@ defmodule Ash.Resource.Relationships.ManyToMany do
|
|||
[
|
||||
source_attribute_on_join_resource: [
|
||||
type: :atom,
|
||||
required: false,
|
||||
doc:
|
||||
"The attribute on the join resource that should line up with `source_attribute` on this resource. Defaults to `<snake_cased_last_part_of_source_module_name>_id`."
|
||||
],
|
||||
destination_attribute_on_join_resource: [
|
||||
type: :atom,
|
||||
required: false,
|
||||
doc:
|
||||
"The attribute on the join resource that should line up with `destination_attribute` on the related resource. Defaults to `<snake_cased_last_part_of_destination_module_name>_id`."
|
||||
],
|
||||
through: [
|
||||
type: Ash.OptionsHelpers.ash_resource(),
|
||||
required: true,
|
||||
doc: "The resource to use as the join resource."
|
||||
],
|
||||
join_relationship: [
|
||||
|
|
|
@ -4,7 +4,7 @@ defmodule Ash.Resource.Transformers.CreateJoinRelationship do
|
|||
"""
|
||||
use Spark.Dsl.Transformer
|
||||
|
||||
alias Spark.Dsl.Transformer
|
||||
alias Spark.{Dsl.Transformer, Error.DslError}
|
||||
|
||||
@extension Ash.Resource.Dsl
|
||||
|
||||
|
@ -12,38 +12,63 @@ defmodule Ash.Resource.Transformers.CreateJoinRelationship do
|
|||
dsl_state
|
||||
|> Transformer.get_entities([:relationships])
|
||||
|> Enum.filter(&(&1.type == :many_to_many))
|
||||
|> Enum.reject(fn relationship ->
|
||||
|> Enum.reduce_while({:ok, dsl_state}, fn relationship, {:ok, dsl_state} ->
|
||||
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
|
||||
|> case do
|
||||
nil when relationship.through == nil ->
|
||||
error =
|
||||
DslError.exception(
|
||||
path: [:relationships, relationship.name],
|
||||
message:
|
||||
"Either `through` or `join_relationship` with an existing relationship is required."
|
||||
)
|
||||
|
||||
{: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)
|
||||
)
|
||||
{:halt, {:error, error}}
|
||||
|
||||
relationship =
|
||||
Map.put(
|
||||
relationship,
|
||||
:autogenerated_join_relationship_of,
|
||||
autogenerated_join_relationship_of
|
||||
)
|
||||
nil ->
|
||||
{:ok, join_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)
|
||||
)
|
||||
|
||||
{:ok, Transformer.add_entity(dsl_state, [:relationships], relationship)}
|
||||
join_relationship =
|
||||
Map.put(join_relationship, :autogenerated_join_relationship_of, relationship.name)
|
||||
|
||||
dsl_state = Transformer.add_entity(dsl_state, [:relationships], join_relationship)
|
||||
|
||||
{:cont, {:ok, dsl_state}}
|
||||
|
||||
join_relationship ->
|
||||
relationship =
|
||||
%{
|
||||
relationship
|
||||
| through: join_relationship.destination,
|
||||
destination_attribute_on_join_resource: join_relationship.destination_attribute
|
||||
}
|
||||
|
||||
dsl_state =
|
||||
Transformer.replace_entity(
|
||||
dsl_state,
|
||||
[:relationships],
|
||||
relationship,
|
||||
&(&1.name == relationship.name)
|
||||
)
|
||||
|
||||
{:cont, {:ok, dsl_state}}
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue