Packages
ash
3.4.3
3.29.3
3.29.2
3.29.1
3.29.0
3.28.0
3.27.8
3.27.7
3.27.6
3.27.5
3.27.4
3.27.3
3.27.2
3.27.1
3.27.0
3.26.0
3.25.2
3.25.1
3.25.0
retired
3.24.7
3.24.6
3.24.5
3.24.4
3.24.3
3.24.2
3.24.1
3.24.0
3.23.1
3.23.0
3.22.2
3.22.1
3.22.0
3.21.3
3.21.2
3.21.1
3.21.0
3.20.0
3.19.3
3.19.2
3.19.1
3.19.0
3.18.0
3.17.1
3.17.0
3.16.0
3.15.0
3.14.1
3.14.0
retired
3.13.2
3.13.1
3.13.0
3.12.0
3.11.3
3.11.2
3.11.1
3.11.0
3.10.1
3.10.0
3.9.0
3.8.0
3.7.6
3.7.5
3.7.4
3.7.3
3.7.2
3.7.1
3.7.0
retired
3.6.3
retired
3.6.2
3.6.1
3.6.0
3.5.43
3.5.42
3.5.41
3.5.40
3.5.39
3.5.38
3.5.37
3.5.36
3.5.35
3.5.34
3.5.33
3.5.32
3.5.31
3.5.30
3.5.29
3.5.28
3.5.27
3.5.26
3.5.25
3.5.24
3.5.23
3.5.22
3.5.21
3.5.20
3.5.19
3.5.18
3.5.17
3.5.16
3.5.15
3.5.14
3.5.13
3.5.12
3.5.11
3.5.10
3.5.9
3.5.8
3.5.7
3.5.6
3.5.5
3.5.4
3.5.3
3.5.2
3.5.1
3.5.0
3.4.74
retired
3.4.73
3.4.72
3.4.71
3.4.70
3.4.69
3.4.68
3.4.67
3.4.66
3.4.65
3.4.64
3.4.63
3.4.62
3.4.61
3.4.60
3.4.59
3.4.58
3.4.57
3.4.56
3.4.55
3.4.54
3.4.53
3.4.52
3.4.51
3.4.50
3.4.49
3.4.48
3.4.47
3.4.46
3.4.45
3.4.44
3.4.43
3.4.42
3.4.41
3.4.40
3.4.39
3.4.38
3.4.37
3.4.36
3.4.35
3.4.34
3.4.33
3.4.32
3.4.31
3.4.30
3.4.29
3.4.28
3.4.27
3.4.26
3.4.25
3.4.24
3.4.23
3.4.22
3.4.21
3.4.20
3.4.19
3.4.18
3.4.17
3.4.16
3.4.15
3.4.14
3.4.13
3.4.12
3.4.11
3.4.10
3.4.9
3.4.8
3.4.7
3.4.6
3.4.5
3.4.4
3.4.3
3.4.2
3.4.1
3.4.0
3.3.3
3.3.2
3.3.1
3.3.0
3.2.6
3.2.5
3.2.4
3.2.3
3.2.2
3.2.1
3.2.0
3.1.8
3.1.7
3.1.6
3.1.5
3.1.4
3.1.3
3.1.2
3.1.1
3.1.0
3.0.16
3.0.15
3.0.14
3.0.13
3.0.12
3.0.11
3.0.10
3.0.9
3.0.8
3.0.7
3.0.6
3.0.5
3.0.4
3.0.3
3.0.2
3.0.1
3.0.0
3.0.0-rc.46
3.0.0-rc.45
3.0.0-rc.44
3.0.0-rc.43
3.0.0-rc.42
3.0.0-rc.41
3.0.0-rc.40
3.0.0-rc.39
3.0.0-rc.38
3.0.0-rc.37
3.0.0-rc.36
3.0.0-rc.35
3.0.0-rc.34
3.0.0-rc.33
3.0.0-rc.32
3.0.0-rc.31
3.0.0-rc.29
3.0.0-rc.28
3.0.0-rc.27
3.0.0-rc.26
3.0.0-rc.25
3.0.0-rc.24
3.0.0-rc.23
3.0.0-rc.22
3.0.0-rc.21
3.0.0-rc.20
3.0.0-rc.19
3.0.0-rc.18
3.0.0-rc.17
3.0.0-rc.16
3.0.0-rc.15
3.0.0-rc.14
3.0.0-rc.13
3.0.0-rc.12
3.0.0-rc.11
3.0.0-rc.10
3.0.0-rc.9
3.0.0-rc.8
3.0.0-rc.7
3.0.0-rc.6
3.0.0-rc.5
3.0.0-rc.4
3.0.0-rc.3
3.0.0-rc.1
3.0.0-rc.0
2.21.15
2.21.14
2.21.13
2.21.12
2.21.11
2.21.10
2.21.9
2.21.8
2.21.7
2.21.6
2.21.5
2.21.4
2.21.3
2.21.2
2.21.1
2.21.0
2.20.3
2.20.2
2.20.1
2.20.0
2.19.14
2.19.13
2.19.12
2.19.11
2.19.10
2.19.9
2.19.8
2.19.7
2.19.6
2.19.5
2.19.4
2.19.3
retired
2.19.2
retired
2.19.1
retired
2.19.0
retired
2.18.2
2.18.1
2.18.0
2.17.24
2.17.23
2.17.22
2.17.21
2.17.20
2.17.19
2.17.18
2.17.17
2.17.16
2.17.15
2.17.14
2.17.13
2.17.12
2.17.11
2.17.10
2.17.9
2.17.8
2.17.7
2.17.6
2.17.5
2.17.4
2.17.3
2.17.2
2.17.1
2.17.0
2.16.1
2.16.0
2.15.20
2.15.19
2.15.18
2.15.17
2.15.16
2.15.15
2.15.14
2.15.13
2.15.12
2.15.11
2.15.10
2.15.9
2.15.8
2.15.7
2.15.6
2.15.5
2.15.4
2.15.2
2.15.1
2.15.0
2.14.21
2.14.20
2.14.19
2.14.18
2.14.17
2.14.16
2.14.15
2.14.14
2.14.13
2.14.12
2.14.11
2.14.10
2.14.9
2.14.8
2.14.7
2.14.6
2.14.5
2.14.4
2.14.3
2.14.2
2.14.1
2.14.0
2.13.4
retired
2.13.3
2.13.2
2.13.1
2.13.0
2.12.1
2.12.0
2.11.11
2.11.10
2.11.9
2.11.8
2.11.7
2.11.6
2.11.5
2.11.4
2.11.3
2.11.2
2.11.1
2.11.0
2.11.0-rc.3
2.11.0-rc.2
2.11.0-rc.1
2.11.0-rc.0
2.10.2
2.10.1
2.10.0
2.9.29
2.9.28
2.9.27
2.9.26
2.9.25
2.9.24
2.9.23
2.9.22
2.9.21
2.9.20
2.9.19
2.9.18
2.9.17
2.9.16
2.9.15
2.9.14
2.9.13
2.9.12
2.9.11
2.9.10
2.9.9
2.9.8
2.9.7
2.9.6
2.9.5
2.9.4
2.9.3
2.9.2
2.9.1
2.9.0
2.8.1
2.8.0
2.7.1
2.7.0
2.6.31
2.6.30
2.6.29
2.6.28
2.6.27
2.6.26
2.6.25
2.6.24
2.6.23
2.6.22
2.6.21
2.6.20
2.6.19
2.6.18
2.6.17
2.6.16
2.6.15
2.6.14
2.6.13
2.6.11
2.6.10
2.6.9
2.6.8
2.6.7
2.6.6
2.6.5
2.6.4
2.6.3
2.6.2
2.6.1
2.6.0
2.5.16
2.5.15
2.5.14
2.5.13
2.5.12
2.5.11
2.5.10
2.5.9
2.5.8
2.5.7
2.5.6
2.5.5
2.5.4
2.5.3
2.5.2
2.5.1
2.5.0
2.5.0-rc.6
2.5.0-rc.5
2.5.0-rc.4
2.5.0-rc.3
2.5.0-rc.2
2.5.0-rc.1
2.5.0-rc.0
2.4.30
2.4.29
2.4.28
2.4.27
2.4.26
2.4.25
2.4.24
2.4.23
2.4.22
2.4.21
2.4.20
2.4.19
2.4.18
2.4.17
2.4.16
2.4.15
2.4.14
2.4.13
2.4.12
2.4.11
2.4.10
2.4.9
2.4.8
2.4.7
2.4.6
2.4.5
2.4.4
2.4.3
2.4.2
2.4.1
2.4.0
2.3.0
2.2.0
2.1.0
2.0.0
2.0.0-rc.15
2.0.0-rc.14
2.0.0-rc.13
2.0.0-rc.12
2.0.0-rc.11
2.0.0-rc.10
2.0.0-rc.9
2.0.0-rc.8
2.0.0-rc.7
2.0.0-rc.6
2.0.0-rc.5
2.0.0-rc.4
2.0.0-rc.3
2.0.0-rc.2
2.0.0-rc.1
2.0.0-rc.0
2.0.0-pre.8
2.0.0-pre.7
2.0.0-pre.6
2.0.0-pre.5
2.0.0-pre.4
2.0.0-pre.3
2.0.0-pre.2
2.0.0-pre.1
2.0.0-pre.0
1.53.3
1.53.2
1.53.0
1.52.0-rc.22
1.52.0-rc.21
1.52.0-rc.20
1.52.0-rc.19
1.52.0-rc.18
1.52.0-rc.17
1.52.0-rc.16
1.52.0-rc.15
1.52.0-rc.14
1.52.0-rc.13
1.52.0-rc.12
1.52.0-rc.11
1.52.0-rc.10
1.52.0-rc.9
1.52.0-rc.8
1.52.0-rc.7
1.52.0-rc.6
1.52.0-rc.5
1.52.0-rc.4
1.52.0-rc.3
1.52.0-rc.2
1.52.0-rc.1
1.52.0-rc.0
1.51.2
1.51.1
retired
1.51.0
1.50.21
1.50.20
1.50.19
1.50.18
1.50.17
1.50.16
1.50.15
1.50.14
1.50.13
1.50.12
1.50.11
1.50.10
1.50.9
1.50.8
1.50.7
1.50.6
1.50.5
1.50.4
1.50.3
1.50.2
1.50.1
1.50.0
1.49.0
1.48.0-rc.30
1.48.0-rc.29
1.48.0-rc.28
1.48.0-rc.27
1.48.0-rc.26
1.48.0-rc.25
1.48.0-rc.24
1.48.0-rc.23
1.48.0-rc.22
1.48.0-rc.21
1.48.0-rc.20
1.48.0-rc.19
1.48.0-rc.18
1.48.0-rc.17
1.48.0-rc.16
1.48.0-rc.15
1.48.0-rc.14
1.48.0-rc.13
1.48.0-rc.12
1.48.0-rc.11
1.48.0-rc.10
1.48.0-rc.9
1.48.0-rc.8
1.48.0-rc.7
1.48.0-rc.6
1.48.0-rc.5
1.48.0-rc.4
1.48.0-rc.3
1.48.0-rc.2
1.48.0-rc.1
1.48.0-rc.0
1.47.12
1.47.11
1.47.10
1.47.9
1.47.8
1.47.7
1.47.6
1.47.5
1.47.4
1.47.3
1.47.2
1.47.1
1.47.0
1.46.13
1.46.12
1.46.11
1.46.10
1.46.9
1.46.8
1.46.7
1.46.6
1.46.5
1.46.4
1.46.3
1.46.2
1.46.1
1.46.0
1.45.0-rc9
1.45.0-rc8
1.45.0-rc7
1.45.0-rc6
1.45.0-rc5
1.45.0-rc4
1.45.0-rc3
1.45.0-rc20
1.45.0-rc2
1.45.0-rc19
1.45.0-rc18
1.45.0-rc17
1.45.0-rc16
1.45.0-rc15
1.45.0-rc14
1.45.0-rc13
1.45.0-rc12
1.45.0-rc11
1.45.0-rc10
1.45.0-rc1
1.45.0-rc0
1.44.13
1.44.12
1.44.11
1.44.10
1.44.9
1.44.8
1.44.7
1.44.6
1.44.5
1.44.4
1.44.3
1.44.2
1.44.1
1.44.0
1.43.12
1.43.11
1.43.10
1.43.9
1.43.8
1.43.7
1.43.6
1.43.5
1.43.4
1.43.3
1.43.2
1.43.1
1.43.0
1.42.0
1.41.12
1.41.11
1.41.10
1.41.9
1.41.8
1.41.7
1.41.6
1.41.5
1.41.4
1.41.3
1.41.2
1.41.1
1.41.0
1.40.0
1.39.7
1.39.6
1.39.5
1.39.4
1.39.3
1.39.2
1.39.1
1.39.0
1.38.0
1.37.2
1.37.1
1.37.0
1.36.22
1.36.21
1.36.19
1.36.18
1.36.17
1.36.16
1.36.15
1.36.14
1.36.13
1.36.12
1.36.11
1.36.10
1.36.9
1.36.8
1.36.7
1.36.6
1.36.5
1.36.4
1.36.3
1.36.2
1.36.0
1.35.1
1.35.0
1.34.9
1.34.8
1.34.7
1.34.6
1.34.5
1.34.4
1.34.3
1.34.2
1.34.1
1.34.0
1.33.0
1.32.2
1.32.1
1.32.0
1.31.1
1.31.0
1.30.2
1.30.1
1.29.0-rc1
1.29.0-rc0
1.28.1
1.28.0
1.27.1
1.27.0
1.26.13
1.26.12
1.26.11
1.26.10
1.26.9
1.26.8
1.26.7
1.26.6
1.26.5
1.26.4
1.26.2
1.26.1
1.26.0
1.25.8
1.25.7
1.25.6
1.25.5
1.25.4
1.25.3
1.25.2
1.25.1
1.25.0
1.24.2
1.24.1
1.24.0
1.23.3
1.23.2
1.23.1
1.23.0
1.22.1
1.22.0
1.20.1
1.20.0
1.19.1
1.19.0
1.18.1
1.18.0
1.17.1
1.17.0
1.16.2
1.15.1
1.15.0
1.14.0
1.13.4
1.13.3
1.13.2
1.13.1
1.13.0
1.12.0
1.11.1
1.11.0
1.10.0
1.9.0
1.8.0
1.7.0
1.6.8
1.6.7
1.6.6
1.6.5
1.6.4
1.6.3
1.6.2
1.6.1
1.6.0
1.5.1
1.5.0
1.4.1
1.4.0
1.3.1
1.3.0
1.2.1
1.2.0
1.1.3
1.1.2
1.1.0
1.0.3
1.0.2
1.0.1
1.0.0
0.13.1
0.13.0
0.12.0
0.10.0
0.9.1
0.9.0
0.8.0
0.7.0
0.6.5
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.2
0.5.1
0.5.0
0.4.0
0.3.0
0.2.0
0.1.9
0.1.8
0.1.3
0.1.1
0.1.0
A declarative, extensible framework for building Elixir applications.
Security advisory:
This version has known vulnerabilities.
View advisories
Current section
Files
Jump to
Current section
Files
lib/ash/resource/schema.ex
defmodule Ash.Schema do
@moduledoc false
# Defines an ecto schema for a resource.
# This defines struct representation of a resource. Data layers can rely on this
# schema for persistence.
defmacro define_schema do
if Ash.Resource.Info.embedded?(__CALLER__.module) do
quote unquote: false do
if Ash.Schema.define?(__MODULE__) do
alias Ash.Query.Aggregate
use Ecto.Schema
@primary_key false
embedded_schema do
for attribute <- Ash.Resource.Info.attributes(__MODULE__),
attribute.name not in Ash.Resource.reserved_names() do
read_after_writes? = attribute.generated? and is_nil(attribute.default)
constraint_opts =
case attribute.type do
{:array, _type} ->
attribute.constraints[:items] || []
_ ->
attribute.constraints
end
field(
attribute.name,
Ash.Type.ecto_type(Ash.Schema.not_a_resource!(attribute.type)),
Keyword.merge(constraint_opts,
primary_key: attribute.primary_key?,
read_after_writes: read_after_writes?,
redact: attribute.sensitive?,
source: attribute.source,
default: Ash.Schema.attribute_default(attribute.default)
)
)
end
field(:aggregates, :map, virtual: true, default: %{})
field(:calculations, :map, virtual: true, default: %{})
field(:__metadata__, :map, virtual: true, default: %{}, redact: true)
field(:__order__, :integer, virtual: true, redact: true)
field(:__lateral_join_source__, :integer, virtual: true, redact: true)
struct_fields_name =
if Module.get_attribute(__MODULE__, :struct_fields) do
:struct_fields
else
:ecto_struct_fields
end
Module.register_attribute(__MODULE__, :ash_struct_fields, accumulate: true)
for field <- Module.get_attribute(__MODULE__, struct_fields_name) do
Module.put_attribute(__MODULE__, :ash_struct_fields, field)
end
for relationship <- Ash.Resource.Info.relationships(__MODULE__),
relationship.name not in Ash.Resource.reserved_names() do
Module.put_attribute(
__MODULE__,
:ash_struct_fields,
{relationship.name, %Ash.NotLoaded{type: :relationship, field: relationship.name}}
)
end
for aggregate <- Ash.Resource.Info.aggregates(__MODULE__),
aggregate.name not in Ash.Resource.reserved_names() do
{:ok, type, _} =
if aggregate.kind == :custom do
{:ok, aggregate.type, []}
else
Aggregate.kind_to_type(aggregate.kind, :string, [])
end
field(
aggregate.name,
Ash.Type.ecto_type(Ash.Schema.not_a_resource!(type)),
virtual: true,
redact: aggregate.sensitive?
)
Module.put_attribute(
__MODULE__,
:ash_struct_fields,
{aggregate.name, %Ash.NotLoaded{type: :aggregate, field: aggregate.name}}
)
end
for calculation <- Ash.Resource.Info.calculations(__MODULE__),
calculation.name not in Ash.Resource.reserved_names() do
{mod, _} = calculation.calculation
field(
calculation.name,
Ash.Type.ecto_type(Ash.Schema.not_a_resource!(calculation.type)),
virtual: true,
redact: calculation.sensitive?
)
Module.put_attribute(
__MODULE__,
:ash_struct_fields,
{calculation.name, %Ash.NotLoaded{type: :calculation, field: calculation.name}}
)
end
struct_fields = Module.get_attribute(__MODULE__, :ash_struct_fields)
Module.delete_attribute(__MODULE__, struct_fields_name)
Module.register_attribute(__MODULE__, struct_fields_name, accumulate: true)
Enum.each(struct_fields, &Module.put_attribute(__MODULE__, struct_fields_name, &1))
end
after_compile =
@after_compile -- [{Ecto.Schema, :__after_compile__}]
Module.delete_attribute(__MODULE__, :after_compile)
Module.register_attribute(__MODULE__, :after_compile, accumulate: true)
for compile_hook <- after_compile do
@after_compile compile_hook
end
end
end
else
quote unquote: false do
if Ash.Schema.define?(__MODULE__) do
alias Ash.Query.Aggregate
use Ecto.Schema
@primary_key false
schema Ash.DataLayer.source(__MODULE__) do
for attribute <- Ash.Resource.Info.attributes(__MODULE__),
attribute.name not in Ash.Resource.reserved_names() do
read_after_writes? = attribute.generated? and is_nil(attribute.default)
constraint_opts =
case attribute.type do
{:array, _type} ->
attribute.constraints[:items] || []
_ ->
attribute.constraints
end
field(
attribute.name,
Ash.Type.ecto_type(Ash.Schema.not_a_resource!(attribute.type)),
Keyword.merge(constraint_opts,
primary_key: attribute.primary_key?,
read_after_writes: read_after_writes?,
redact: attribute.sensitive?,
source: attribute.source,
default: Ash.Schema.attribute_default(attribute.default)
)
)
end
field(:aggregates, :map, virtual: true, default: %{})
field(:calculations, :map, virtual: true, default: %{})
field(:__metadata__, :map, virtual: true, default: %{}, redact: true)
field(:__order__, :integer, virtual: true, redact: true)
field(:__lateral_join_source__, :integer, virtual: true, redact: true)
struct_fields_name =
if Module.get_attribute(__MODULE__, :struct_fields) do
:struct_fields
else
:ecto_struct_fields
end
Module.register_attribute(__MODULE__, :ash_struct_fields, accumulate: true)
for field <- Module.get_attribute(__MODULE__, struct_fields_name) do
Module.put_attribute(__MODULE__, :ash_struct_fields, field)
end
for relationship <- Ash.Resource.Info.relationships(__MODULE__),
relationship.name not in Ash.Resource.reserved_names() do
case relationship do
%{no_attributes?: true} ->
:ok
%{manual?: true} ->
:ok
%{manual: manual} when not is_nil(manual) ->
:ok
%{type: :belongs_to} ->
belongs_to relationship.name, relationship.destination,
define_field: false,
references: relationship.destination_attribute,
foreign_key: relationship.source_attribute
%{type: :has_many} ->
has_many relationship.name, relationship.destination,
foreign_key: relationship.destination_attribute,
references: relationship.source_attribute
%{type: :has_one} ->
has_one relationship.name, relationship.destination,
foreign_key: relationship.destination_attribute,
references: relationship.source_attribute
%{type: :many_to_many} ->
many_to_many relationship.name, relationship.destination,
join_through: relationship.through,
join_keys: [
{relationship.source_attribute_on_join_resource,
relationship.source_attribute},
{relationship.destination_attribute_on_join_resource,
relationship.destination_attribute}
]
end
Module.put_attribute(
__MODULE__,
:ash_struct_fields,
{relationship.name, %Ash.NotLoaded{type: :relationship, field: relationship.name}}
)
end
for aggregate <- Ash.Resource.Info.aggregates(__MODULE__),
aggregate.name not in Ash.Resource.reserved_names() do
{:ok, type, _} =
if aggregate.kind == :custom do
{:ok, aggregate.type, []}
else
Aggregate.kind_to_type(aggregate.kind, :string, [])
end
field(
aggregate.name,
Ash.Type.ecto_type(Ash.Schema.not_a_resource!(type)),
virtual: true,
redact: aggregate.sensitive?
)
Module.put_attribute(
__MODULE__,
:ash_struct_fields,
{aggregate.name, %Ash.NotLoaded{type: :aggregate, field: aggregate.name}}
)
end
for calculation <- Ash.Resource.Info.calculations(__MODULE__),
calculation.name not in Ash.Resource.reserved_names() do
{mod, _} = calculation.calculation
field(
calculation.name,
Ash.Type.ecto_type(Ash.Schema.not_a_resource!(calculation.type)),
virtual: true,
redact: calculation.sensitive?
)
Module.put_attribute(
__MODULE__,
:ash_struct_fields,
{calculation.name, %Ash.NotLoaded{type: :calculation, field: calculation.name}}
)
end
struct_fields = Module.get_attribute(__MODULE__, :ash_struct_fields)
Module.delete_attribute(__MODULE__, struct_fields_name)
Module.register_attribute(__MODULE__, struct_fields_name, accumulate: true)
Enum.each(struct_fields, &Module.put_attribute(__MODULE__, struct_fields_name, &1))
end
unless Kernel.Typespec.defines_type?(__MODULE__, {:t, 0}) do
@type t :: %__MODULE__{}
end
after_compile =
@after_compile -- [{Ecto.Schema, :__after_compile__}]
Module.delete_attribute(__MODULE__, :after_compile)
Module.register_attribute(__MODULE__, :after_compile, accumulate: true)
for compile_hook <- after_compile do
@after_compile compile_hook
end
end
end
end
end
def define?(resource) do
has_action?(resource) or !Enum.empty?(Ash.Resource.Info.fields(resource))
end
defp has_action?(resource) do
resource
|> Ash.Resource.Info.actions()
|> Enum.any?(&(&1.type != :action))
end
@doc false
def not_a_resource!({:array, type}) do
{:array, not_a_resource!(type)}
end
def not_a_resource!(module) when is_atom(module) do
type =
if Ash.Type.NewType.new_type?(module) do
Ash.Type.NewType.subtype_of(module)
else
module
end
if Ash.Resource.Info.resource?(type) && !Ash.Resource.Info.embedded?(type) do
raise """
Non-embedded resources can not be used as types.
Got #{inspect(module)}
To use them as a type, instead use the `:struct` type, with the `instance_of` constraint.
For example:
attribute :foo, :struct, constraints: [instance_of: #{inspect(module)}]
Or as an array:
attribute :foo, {:array, :struct}, constraints: [items: [instance_of: #{inspect(module)}]]
You can disable this warning by setting `config :ash, allow_resources_as_types: true` in your config.
In 3.0, the flag to disable this behaviour will not be available.
"""
else
module
end
end
def not_a_resource!(type), do: type
def attribute_default(fun) when is_function(fun), do: nil
def attribute_default({_mod, _func, _args}), do: nil
def attribute_default(value), do: value
end