defmodule Ash.Resource.Relationships.BelongsTo do
@moduledoc "Represents a belongs_to relationship on a resource"
defstruct [
:name,
:destination,
:primary_key?,
:define_attribute?,
:attribute_type,
:destination_attribute,
:public?,
:source_attribute,
:source,
:read_action,
:domain,
:not_found_message,
:violation_message,
:allow_nil?,
:filter,
:sort,
:default_sort,
:writable?,
:context,
:description,
:attribute_writable?,
:attribute_public?,
filters: [],
filterable?: true,
sortable?: true,
allow_forbidden_field?: false,
authorize_read_with: :filter,
validate_destination_attribute?: true,
cardinality: :one,
type: :belongs_to
]
@type t :: %__MODULE__{
type: :belongs_to,
cardinality: :one,
writable?: boolean,
name: atom,
read_action: atom,
filter: Ash.Filter.t() | nil,
filters: list(any()),
source: Ash.Resource.t(),
destination: Ash.Resource.t(),
allow_nil?: boolean,
primary_key?: boolean,
define_attribute?: boolean,
attribute_type: term,
writable?: boolean,
attribute_writable?: boolean,
attribute_public?: boolean,
destination_attribute: atom,
public?: boolean,
filterable?: boolean,
sortable?: boolean,
source_attribute: atom | nil,
description: String.t(),
sort: Keyword.t() | nil,
default_sort: Keyword.t() | nil
}
import Ash.Resource.Relationships.SharedOptions
@global_opts shared_options()
|> Spark.Options.Helpers.set_default!(:destination_attribute, :id)
|> Spark.Options.Helpers.append_doc!(:source_attribute, "Defaults to <name>_id")
|> Keyword.delete(:could_be_related_at_creation?)
@opt_schema Spark.Options.merge(
[
primary_key?: [
type: :boolean,
default: false,
doc:
"Whether the generated attribute is, or is part of, the primary key of a resource."
],
allow_nil?: [
type: :boolean,
default: true,
doc:
"Whether this relationship must always be present, e.g: must be included on creation, and never removed (it may be modified). The generated attribute will not allow nil values."
],
attribute_writable?: [
type: :boolean,
doc: """
Whether the generated attribute will be marked as writable. If not set, it will default to the relationship's `writable?` setting.
"""
],
attribute_public?: [
type: :boolean,
doc: """
Whether or not the generated attribute will be public. If not set, it will default to the relationship's `public?` setting.
"""
],
define_attribute?: [
type: :boolean,
default: true,
doc:
"If set to `false` an attribute is not created on the resource for this relationship, and one must be manually added in `attributes`, invalidating many other options."
],
attribute_type: [
type: :any,
default: Application.compile_env(:ash, :default_belongs_to_type, :uuid),
doc: "The type of the generated created attribute. See `Ash.Type` for more."
]
],
@global_opts,
"Relationship Options"
)
@doc false
def opt_schema, do: @opt_schema
@doc false
# sobelow_skip ["DOS.BinToAtom"]
def transform(
%{
source_attribute: source_attribute,
name: name,
attribute_public?: attribute_public?,
attribute_writable?: attribute_writable?,
writable?: writable?,
public?: public?
} = relationship
) do
attribute_public? =
if is_nil(attribute_public?) do
public?
else
attribute_public?
end
attribute_writable? =
if is_nil(attribute_writable?) do
writable?
else
attribute_writable?
end
{:ok,
%{
relationship
| source_attribute: source_attribute || :"#{name}_id",
attribute_public?: attribute_public?,
attribute_writable?: attribute_writable?
}
|> Ash.Resource.Actions.Read.concat_filters()}
end
end