Packages
ash_phoenix
0.4.11
2.3.24
2.3.23
2.3.22
2.3.21
2.3.20
2.3.19
2.3.18
2.3.17
2.3.16
2.3.15
2.3.14
2.3.13
2.3.12
2.3.11
2.3.10
2.3.9
2.3.8
2.3.7
2.3.6
2.3.5
2.3.4
2.3.3
2.3.2
2.3.1
2.3.0
2.2.0
2.1.26
2.1.25
2.1.24
2.1.23
2.1.22
2.1.21
2.1.20
2.1.19
2.1.18
2.1.17
2.1.16
2.1.15
2.1.14
2.1.13
2.1.12
2.1.11
2.1.10
2.1.9
2.1.8
2.1.7
2.1.6
2.1.5
2.1.4
2.1.3
2.1.2
2.1.1
2.1.0
2.0.4
2.0.3
2.0.2
2.0.1
2.0.0
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
1.3.7
1.3.6
1.3.5
1.3.4
1.3.3
1.3.2
1.3.1
1.3.0
1.2.26
1.2.25
1.2.24
1.2.23
1.2.22
1.2.21
1.2.20
1.2.19
1.2.18
1.2.17
1.2.16
1.2.15
1.2.14
1.2.13
1.2.12
1.2.11
1.2.10
1.2.9
1.2.8
1.2.7
1.2.6
1.2.5
1.2.4
1.2.3
1.2.2
1.2.1
1.2.0
1.1.2
1.1.1
1.1.0
1.1.0-rc.3
1.1.0-rc.2
1.1.0-rc.1
1.1.0-rc.0
1.0.0-rc.1
1.0.0-rc.0
1.0.0-pre.2
1.0.0-pre.1
1.0.0-pre.0
0.7.7
0.7.6-rc.0
0.7.5
0.7.4
0.7.3
0.7.2-rc.2
0.7.2-rc.1
0.7.2-rc.0
0.7.1
0.7.0
0.6.0-rc.7
0.6.0-rc.6
0.6.0-rc.5
0.6.0-rc.4
0.6.0-rc.3
0.6.0-rc.2
0.6.0-rc.1
0.6.0-rc.0
0.5.19-rc.2
0.5.19-rc.1
0.5.19-rc.0
0.5.18
0.5.17
0.5.16
0.5.15
0.5.14
0.5.13
0.5.12
0.5.11
0.5.10
0.5.9
0.5.8
0.5.7
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.24
0.4.23
0.4.23-rc.1
0.4.23-rc.0
0.4.22-rc2
0.4.22-rc1
0.4.21
0.4.20
0.4.19
0.4.18
0.4.17
0.4.16
0.4.15
0.4.14
0.4.13
0.4.12
0.4.11
0.4.10
0.4.9
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.2
0.3.1
0.3.0
0.2.3
0.2.2
0.2.1
0.2.0
0.1.2
0.1.1
0.1.0
Utilities for integrating Ash and Phoenix
Current section
Files
Jump to
Current section
Files
lib/ash_phoenix/form_data/helpers.ex
defmodule AshPhoenix.FormData.Helpers do
@moduledoc false
def get_argument(nil, _), do: nil
def get_argument(action, field) when is_atom(field) do
Enum.find(action.arguments, &(&1.name == field))
end
def get_argument(action, field) when is_binary(field) do
Enum.find(action.arguments, &(to_string(&1.name) == field))
end
def argument_and_manages(changeset, key) do
with action when not is_nil(action) <- changeset.action,
argument when not is_nil(argument) <-
Enum.find(changeset.action.arguments, &(&1.name == key || to_string(&1.name) == key)),
manage_change when not is_nil(manage_change) <-
find_manage_change(argument, changeset.action) do
{argument, manage_change}
else
_ ->
{nil, nil}
end
end
defp find_manage_change(argument, action) do
Enum.find_value(action.changes, fn
%{change: {Ash.Resource.Change.ManageRelationship, opts}} ->
if opts[:argument] == argument.name do
opts[:relationship]
end
_ ->
nil
end)
end
def type_to_form_type(type) do
case Ash.Type.ecto_type(type) do
:integer -> :number_input
:boolean -> :checkbox
:date -> :date_select
:time -> :time_select
:utc_datetime -> :datetime_select
:naive_datetime -> :datetime_select
_ -> :text_input
end
end
def form_for_errors(query, _opts) do
AshPhoenix.errors_for(query)
end
def form_for_name(resource) do
resource
|> Module.split()
|> List.last()
|> Macro.underscore()
end
def get_embedded({:array, type}), do: get_embedded(type)
def get_embedded(type) when is_atom(type) do
if Ash.Resource.Info.embedded?(type) do
type
end
end
def get_embedded(_), do: nil
@doc false
def to_nested_form(
data,
original_changeset,
%{cardinality: _},
resource,
id,
name,
opts
)
when is_list(data) do
changesets = Enum.map(data, &related_data_to_changeset(resource, &1, opts))
changesets =
if AshPhoenix.hiding_errors?(original_changeset) do
Enum.map(changesets, &AshPhoenix.hide_errors/1)
else
changesets
end
for {changeset, index} <- Enum.with_index(changesets) do
index_string = Integer.to_string(index)
hidden =
if changeset.action_type in [:update, :destroy] do
changeset.data
|> Map.take(Ash.Resource.Info.primary_key(changeset.resource))
|> Enum.to_list()
else
[]
end
%Phoenix.HTML.Form{
source: changeset,
impl: Phoenix.HTML.FormData.impl_for(changeset),
id: id <> "_" <> index_string,
name: name <> "[" <> index_string <> "]",
index: index,
errors: form_for_errors(changeset, opts),
data: changeset.data,
params: changeset.params,
hidden: hidden,
options: opts
}
end
end
def to_nested_form(nil, _, _, _, _, _, _) do
nil
end
def to_nested_form(
data,
original_changeset,
%{cardinality: _},
resource,
id,
name,
opts
) do
changeset = related_data_to_changeset(resource, data, opts)
changeset =
if AshPhoenix.hiding_errors?(original_changeset) do
AshPhoenix.hide_errors(changeset)
else
changeset
end
hidden =
if changeset.action_type in [:update, :destroy] do
changeset.data
|> Map.take(Ash.Resource.Info.primary_key(changeset.resource))
|> Enum.to_list()
else
[]
end
%Phoenix.HTML.Form{
source: changeset,
impl: Phoenix.HTML.FormData.impl_for(changeset),
id: id,
name: name,
errors: form_for_errors(changeset, opts),
data: data,
params: changeset.params,
hidden: hidden,
options: opts
}
end
def to_nested_form(
data,
original_changeset,
attribute,
resource,
id,
name,
opts
)
when is_list(data) do
create_action =
action!(resource, :create, attribute.constraints[:create_action] || opts[:create_action]).name
update_action =
action!(resource, :update, attribute.constraints[:update_action] || opts[:update_action]).name
changesets =
data
|> Enum.map(fn data ->
if is_struct(data) do
Ash.Changeset.for_update(data, update_action, %{}, actor: opts[:actor])
else
Ash.Changeset.for_create(resource, create_action, data, actor: opts[:actor])
end
end)
changesets =
if AshPhoenix.hiding_errors?(original_changeset) do
Enum.map(changesets, &AshPhoenix.hide_errors/1)
else
changesets
end
for {changeset, index} <- Enum.with_index(changesets) do
index_string = Integer.to_string(index)
hidden =
if changeset.action_type in [:update, :destroy] do
changeset.data
|> Map.take(Ash.Resource.Info.primary_key(changeset.resource))
|> Enum.to_list()
else
[]
end
%Phoenix.HTML.Form{
source: changeset,
impl: Phoenix.HTML.FormData.impl_for(changeset),
id: id <> "_" <> index_string,
name: name <> "[" <> index_string <> "]",
index: index,
errors: form_for_errors(changeset, opts),
data: changeset.data,
params: changeset.params,
hidden: hidden,
options: opts
}
end
end
def to_nested_form(
data,
original_changeset,
attribute,
resource,
id,
name,
opts
) do
create_action =
action!(resource, :create, attribute.constraints[:create_action] || opts[:create_action]).name
update_action =
action!(resource, :update, attribute.constraints[:update_action] || opts[:update_action]).name
changeset =
cond do
is_struct(data) ->
Ash.Changeset.for_update(data, update_action, %{}, actor: opts[:actor])
is_nil(data) ->
nil
true ->
Ash.Changeset.for_create(resource, create_action, data, actor: opts[:actor])
end
if changeset do
changeset =
if AshPhoenix.hiding_errors?(original_changeset) do
AshPhoenix.hide_errors(changeset)
else
changeset
end
hidden =
if changeset.action_type in [:update, :destroy] do
changeset.data
|> Map.take(Ash.Resource.Info.primary_key(changeset.resource))
|> Enum.to_list()
else
[]
end
%Phoenix.HTML.Form{
source: changeset,
impl: Phoenix.HTML.FormData.impl_for(changeset),
id: id,
name: name,
errors: form_for_errors(changeset, opts),
data: data,
params: changeset.params,
hidden: hidden,
options: opts
}
end
end
def hidden?(nil), do: false
def hidden?(%_{} = data) do
Ash.Resource.Info.get_metadata(data, :private)[:hidden?]
end
def hidden?(_), do: false
def hide(nil), do: nil
def hide(record) do
Ash.Resource.Info.put_metadata(record, :private, %{hidden?: true})
end
defp related_data_to_changeset(resource, data, opts) do
if is_struct(data) do
if opts[:update_action] == :_raw do
Ash.Changeset.new(data)
else
update_action = action!(resource, :update, opts[:update_action])
Ash.Changeset.for_update(data, update_action.name, %{}, actor: opts[:actor])
end
else
if opts[:create_action] == :_raw do
resource
|> Ash.Changeset.new(take_attributes(data, resource))
|> Map.put(:params, data)
else
create_action = action!(resource, :create, opts[:create_action])
Ash.Changeset.for_create(resource, create_action.name, data, actor: opts[:actor])
end
end
end
def take_attributes(data, resource) do
attributes =
resource
|> Ash.Resource.Info.attributes()
|> Enum.map(&to_string(&1.name))
Map.take(data, attributes)
end
def action!(resource, type, nil) do
case Ash.Resource.Info.primary_action(resource, type) do
nil ->
raise """
No `#{type}_action` configured, and no primary action of type #{type} found on #{
inspect(resource)
}
"""
action ->
action
end
end
def action!(resource, _type, action) do
case Ash.Resource.Info.action(resource, action) do
nil ->
raise """
No such action #{action} on resource #{inspect(resource)}
"""
action ->
action
end
end
end