Packages
ash_phoenix
0.3.1
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/relationship_input.ex
# defmodule AshPhoenix.FormData.RelationshipInput do
# defstruct [:resource, :action]
# defimpl Phoenix.HTML.FormData do
# import AshPhoenix.FormData.Helpers
# @impl true
# def input_type(%{resource: resource, action: action}, _, field) do
# attribute = Ash.Resource.Info.attribute(resource, field)
# if attribute do
# type_to_form_type(attribute.type)
# else
# argument = get_argument(action, field)
# if argument do
# type_to_form_type(argument.type)
# else
# :text_input
# end
# end
# end
# @impl true
# def input_value(input, form, field) do
# case get_changing_value(input, field) do
# {:ok, value} ->
# value
# :error ->
# case Map.fetch(input.data, field) do
# {:ok, value} ->
# value
# _ ->
# Ash.Changeset.get_argument(changeset, field)
# end
# end
# end
# defp get_changing_value(changeset, field) do
# with :error <- Map.fetch(changeset.attributes, field),
# :error <- Map.fetch(changeset.params, field) do
# Map.fetch(changeset.params, to_string(field))
# end
# end
# @impl true
# def to_form(changeset, opts) do
# {name, opts} = Keyword.pop(opts, :as)
# name = to_string(name || form_for_name(changeset.resource))
# id = Keyword.get(opts, :id) || name
# hidden =
# if changeset.action_type == :update do
# changeset.data
# |> Map.take(Ash.Resource.Info.primary_key(changeset.resource))
# |> Enum.to_list()
# else
# []
# end
# %Phoenix.HTML.Form{
# action: changeset.action && changeset.action.name,
# source: Ash.Changeset.put_context(changeset, :form, %{path: []}),
# impl: __MODULE__,
# id: id,
# name: name,
# errors: form_for_errors(changeset, opts),
# data: changeset.data,
# params: changeset.params,
# hidden: hidden,
# options: Keyword.put_new(opts, :method, form_for_method(changeset))
# }
# end
# @impl true
# def to_form(changeset, form, field, opts) do
# {name, opts} = Keyword.pop(opts, :as)
# {id, opts} = Keyword.pop(opts, :id)
# {prepend, opts} = Keyword.pop(opts, :prepend, [])
# {append, opts} = Keyword.pop(opts, :append, [])
# changeset_opts = [skip_defaults: :all]
# id = to_string(id || form.id <> "_#{field}")
# name = to_string(name || form.name <> "[#{field}]")
# arguments =
# if changeset.action do
# changeset.action.arguments
# else
# []
# end
# {source, resource, data, opts} =
# cond do
# attr = Ash.Resource.Info.attribute(changeset.resource, field) ->
# case get_embedded(attr.type) do
# nil ->
# raise "Cannot use `form_for` with an attribute unless the type is an embedded resource"
# resource ->
# data = Ash.Changeset.get_attribute(changeset, attr.name)
# data =
# case attr.type do
# {:array, _} ->
# List.wrap(data)
# _ ->
# data
# end
# {attr, resource, data, opts}
# end
# arg =
# Enum.find(
# arguments,
# &(&1.name == field || to_string(&1.name) == field)
# ) ->
# case get_embedded(arg.type) do
# nil ->
# raise "Cannot use `form_for` with an argument unless the type is an embedded resource"
# resource ->
# data = Ash.Changeset.get_argument(changeset, arg.name)
# data =
# case arg.type do
# {:array, _} ->
# List.wrap(data)
# _ ->
# data
# end
# {arg, resource, data}
# end
# true ->
# raise "Cannot use `form_for` with anything except embedded resources in attributes/arguments"
# end
# data =
# if is_list(data) do
# prepend ++ data ++ append
# else
# data
# end
# data
# |> to_nested_form(changeset, source, resource, id, name, opts, changeset_opts)
# |> List.wrap()
# end
# defp to_nested_form(
# data,
# original_changeset,
# attribute,
# resource,
# id,
# name,
# opts,
# changeset_opts
# )
# when is_list(data) do
# create_action =
# attribute.constraints[:create_action] ||
# Ash.Resource.Info.primary_action!(resource, :create).name
# update_action =
# attribute.constraints[:update_action] ||
# Ash.Resource.Info.primary_action!(resource, :update).name
# changesets =
# data
# |> Enum.map(fn data ->
# if is_struct(data) do
# Ash.Changeset.for_update(data, update_action, %{}, changeset_opts)
# else
# Ash.Changeset.for_create(resource, create_action, data, changeset_opts)
# 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 == :update do
# changeset.data
# |> Map.take(Ash.Resource.Info.primary_key(changeset.resource))
# |> Enum.to_list()
# else
# []
# end
# %Phoenix.HTML.Form{
# action: changeset.action && changeset.action.name,
# source: changeset,
# impl: __MODULE__,
# id: id <> "_" <> index_string,
# name: name <> "[" <> index_string <> "]",
# index: index,
# errors: form_for_errors(changeset, opts),
# data: data,
# params: changeset.params,
# hidden: hidden,
# options: opts
# }
# end
# end
# defp to_nested_form(
# data,
# original_changeset,
# attribute,
# resource,
# id,
# name,
# opts,
# changeset_opts
# ) do
# create_action =
# attribute.constraints[:create_action] ||
# Ash.Resource.Info.primary_action!(resource, :create).name
# update_action =
# attribute.constraints[:update_action] ||
# Ash.Resource.Info.primary_action!(resource, :update).name
# changeset =
# cond do
# is_struct(data) ->
# Ash.Changeset.for_update(data, update_action, %{}, changeset_opts)
# is_nil(data) ->
# nil
# true ->
# Ash.Changeset.for_create(resource, create_action, data, changeset_opts)
# end
# if changeset do
# changeset =
# if AshPhoenix.hiding_errors?(original_changeset) do
# AshPhoenix.hide_errors(changeset)
# else
# changeset
# end
# hidden =
# if changeset.action_type == :update do
# changeset.data
# |> Map.take(Ash.Resource.Info.primary_key(changeset.resource))
# |> Enum.to_list()
# else
# []
# end
# %Phoenix.HTML.Form{
# action: changeset.action && changeset.action.name,
# source: changeset,
# impl: __MODULE__,
# id: id,
# name: name,
# errors: form_for_errors(changeset, opts),
# data: data,
# params: changeset.params,
# hidden: hidden,
# options: opts
# }
# end
# end
# defp get_embedded({:array, type}), do: get_embedded(type)
# defp get_embedded(type) when is_atom(type) do
# if Ash.Resource.Info.embedded?(type) do
# type
# end
# end
# defp get_embedded(_), do: nil
# @impl true
# def input_validations(changeset, _, field) do
# attribute_or_argument =
# Ash.Resource.Info.attribute(changeset.resource, field) ||
# get_argument(changeset.action, field)
# if attribute_or_argument do
# [required: !attribute_or_argument.allow_nil?] ++ type_validations(attribute_or_argument)
# else
# []
# end
# end
# defp type_validations(%{type: Ash.Types.Integer, constraints: constraints}) do
# constraints
# |> Kernel.||([])
# |> Keyword.take([:max, :min])
# |> Keyword.put(:step, 1)
# end
# defp type_validations(%{type: Ash.Types.Decimal, constraints: constraints}) do
# constraints
# |> Kernel.||([])
# |> Keyword.take([:max, :min])
# |> Keyword.put(:step, "any")
# end
# defp type_validations(%{type: Ash.Types.String, constraints: constraints}) do
# if constraints[:trim?] do
# # We should consider using the `match` validation here, but we can't
# # add a title here, so we can't set an error message
# # min_length = to_string(constraints[:min_length])
# # max_length = to_string(constraints[:max_length])
# # [match: "(\S\s*){#{min_length},#{max_length}}"]
# []
# else
# validations =
# if constraints[:min_length] do
# [min_length: constraints[:min_length]]
# else
# []
# end
# if constraints[:min_length] do
# Keyword.put(constraints, :min_length, constraints[:min_length])
# else
# validations
# end
# end
# end
# defp type_validations(_), do: []
# defp form_for_method(%{action_type: :create}), do: "post"
# defp form_for_method(_), do: "put"
# end
# end