ash v1.25.1 Ash.Changeset View Source

Changesets are used to create and update data in Ash.

Create a changeset with new/1 or new/2, and alter the attributes and relationships using the functions provided in this module. Nothing in this module actually incurs changes in a data layer. To commit a changeset, see Ash.Api.create/2 and Ash.Api.update/2.

Primary Keys

For relationship manipulation using append_to_relationship/3, remove_from_relationship/3 and replace_relationship/3 there are three types that can be used for primary keys:

1.) An instance of the resource in question.

2.) If the primary key is just a single field, i.e :id, then a single value, i.e 1

3.) A map of keys to values representing the primary key, i.e %{id: 1} or %{id: 1, org_id: 2}

Join Attributes

For many to many relationships, the attributes on a join relationship may be set while relating items by passing a tuple of the primary key and the changes to be applied. This is done via upserts, so update validations on the join resource are not applied, but create validations are.

For example:

Ash.Changeset.replace_relationship(changeset, :linked_tickets, [
  {1, %{link_type: "blocking"}},
  {a_ticket, %{link_type: "caused_by"}},
  {%{id: 2}, %{link_type: "related_to"}}
])

Link to this section Summary

Functions

Adds an error to the changesets errors list, and marks the change as valid?: false

Adds an after_action hook to the changeset.

Appends a record or a list of records to a relationship. Stacks with previous removals/additions.

Returns the original data with attribute changes merged.

Adds a before_action hook to the changeset.

Adds a change to the changeset, unless the value matches the existing value

Calls change_attribute/3 for each key/value pair provided

Change an attribute only if is not currently being changed

Change an attribute if is not currently being changed, by calling the provided function

Returns true if an attribute exists in the changes

Returns true if a relationship exists in the changes

Remove an argument from the changeset

Gets the new value for an attribute, or :error if it is not being changed

Changes an attribute even if it isn't writable

Force change an attribute if is not currently being changed, by calling the provided function

Gets the changing value or the original value of an attribute

Gets the original value for an attribute

Return a changeset over a resource or a record

Removes a record or a list of records to a relationship. Stacks with previous removals/additions.

Replaces the value of a relationship. Any previous additions/removals are cleared.

Add an argument to the changeset, which will be provided to the action

Merge a map of arguments to the arguments list

Wraps a function in the before/after action hooks of a changeset.

Link to this section Types

Specs

t() :: %Ash.Changeset{
  action_type: term(),
  after_action: term(),
  api: term(),
  arguments: term(),
  attributes: term(),
  before_action: term(),
  change_dependencies: term(),
  context: term(),
  data: term(),
  errors: term(),
  relationships: term(),
  requests: term(),
  resource: term(),
  tenant: term(),
  valid?: term()
}

Link to this section Functions

Link to this function

add_error(changeset, error)

View Source

Specs

add_error(t(), Ash.error()) :: t()

Adds an error to the changesets errors list, and marks the change as valid?: false

Link to this function

after_action(changeset, func)

View Source

Specs

after_action(
  t(),
  (t(), Ash.record() ->
     {:ok, Ash.record()}
     | {:ok, Ash.record(), [Ash.notification()]}
     | {:error, term()})
) :: t()

Adds an after_action hook to the changeset.

Link to this function

append_to_relationship(changeset, relationship, record_or_records)

View Source

Specs

append_to_relationship(t(), atom(), Ash.primary_key() | [Ash.primary_key()]) ::
  t()

Appends a record or a list of records to a relationship. Stacks with previous removals/additions.

Accepts a primary key or a list of primary keys. See the section on "Primary Keys" in the module documentation for more.

For many to many relationships, accepts changes for any join_attributes configured on the resource. See the section on "Join Attributes" in the module documentation for more.

Cannot be used with belongs_to or has_one relationships. See replace_relationship/3 for manipulating belongs_to and has_one relationships.

Link to this function

apply_attributes(changeset)

View Source

Specs

apply_attributes(t()) :: Ash.record()

Returns the original data with attribute changes merged.

Link to this function

before_action(changeset, func)

View Source

Specs

before_action(t(), (t() -> t())) :: t()

Adds a before_action hook to the changeset.

Link to this function

change_attribute(changeset, attribute, value)

View Source

Adds a change to the changeset, unless the value matches the existing value

Link to this function

change_attributes(changeset, changes)

View Source

Specs

change_attributes(t(), map() | Keyword.t()) :: t()

Calls change_attribute/3 for each key/value pair provided

Link to this function

change_new_attribute(changeset, attribute, value)

View Source

Specs

change_new_attribute(t(), atom(), term()) :: t()

Change an attribute only if is not currently being changed

Link to this function

change_new_attribute_lazy(changeset, attribute, func)

View Source

Specs

change_new_attribute_lazy(t(), atom(), (() -> any())) :: t()

Change an attribute if is not currently being changed, by calling the provided function

Use this if you want to only perform some expensive calculation for an attribute value only if there isn't already a change for that attribute

Link to this function

changing_attribute?(changeset, attribute)

View Source

Specs

changing_attribute?(t(), atom()) :: boolean()

Returns true if an attribute exists in the changes

Link to this function

changing_relationship?(changeset, relationship)

View Source

Specs

changing_relationship?(t(), atom()) :: boolean()

Returns true if a relationship exists in the changes

Link to this function

delete_argument(changeset, argument_or_arguments)

View Source

Remove an argument from the changeset

Link to this function

fetch_change(changeset, attribute)

View Source

Specs

fetch_change(t(), atom()) :: {:ok, any()} | :error

Gets the new value for an attribute, or :error if it is not being changed

Link to this function

force_change_attribute(changeset, attribute, value)

View Source

Specs

force_change_attribute(t(), atom(), any()) :: t()

Changes an attribute even if it isn't writable

Link to this function

force_change_attributes(changeset, changes)

View Source

Specs

force_change_attributes(t(), map()) :: t()

Calls force_change_attribute/3 for each key/value pair provided

Link to this function

force_change_new_attribute_lazy(changeset, attribute, func)

View Source

Specs

force_change_new_attribute_lazy(t(), atom(), (() -> any())) :: t()

Force change an attribute if is not currently being changed, by calling the provided function

See change_new_attribute_lazy/3 for more.

Link to this function

get_attribute(changeset, attribute)

View Source

Specs

get_attribute(t(), atom()) :: term()

Gets the changing value or the original value of an attribute

Link to this function

get_data(changeset, attribute)

View Source

Specs

get_data(t(), atom()) :: {:ok, any()} | :error

Gets the original value for an attribute

Link to this function

new(resource, initial_attributes \\ %{})

View Source

Specs

new(Ash.resource() | Ash.record(), initial_attributes :: map()) :: t()

Return a changeset over a resource or a record

Link to this function

put_context(changeset, key, value)

View Source

Specs

put_context(t(), atom(), term()) :: t()
Link to this function

remove_from_relationship(changeset, relationship, record_or_records)

View Source

Specs

remove_from_relationship(t(), atom(), Ash.primary_key() | [Ash.primary_key()]) ::
  t()

Removes a record or a list of records to a relationship. Stacks with previous removals/additions.

Accepts a primary key or a list of primary keys. See the section on "Primary Keys" in the module documentation for more.

Cannot be used with belongs_to or has_one relationships. See replace_relationship/3 for manipulating those relationships.

Link to this function

replace_relationship(changeset, relationship, record_or_records)

View Source

Specs

replace_relationship(t(), atom(), Ash.primary_key() | [Ash.primary_key()] | nil) ::
  t()

Replaces the value of a relationship. Any previous additions/removals are cleared.

Accepts a primary key or a list of primary keys. See the section on "Primary Keys" in the module documentation for more.

For many to many relationships, accepts changes for any join_attributes configured on the resource. See the section on "Join Attributes" in the module documentation for more.

For a has_many or many_to_many relationship, this means removing any currently related records that are not present in the replacement list, and creating any that do not exist in the data layer.

For a belongs_to or has_one, replace with a nil value to unset a relationship.

Link to this function

set_argument(changeset, argument, value)

View Source

Add an argument to the changeset, which will be provided to the action

Link to this function

set_arguments(changeset, map)

View Source

Merge a map of arguments to the arguments list

Link to this function

set_context(changeset, map)

View Source

Specs

set_context(t(), map()) :: t()
Link to this function

set_tenant(changeset, tenant)

View Source

Specs

set_tenant(t(), String.t()) :: t()
Link to this function

with_hooks(changeset, func)

View Source

Specs

with_hooks(
  t(),
  (t() ->
     {:ok, Ash.record(), %{notifications: [Ash.notification()]}}
     | {:error, term()})
) :: {:ok, term()} | {:error, term()}

Wraps a function in the before/after action hooks of a changeset.

The function takes a changeset and if it returns {:ok, result}, the result will be passed through the after action hooks.