Form identity and source DSL

v0.0.1

The identity and source sections of a resource's form block name the form, set the Ash actions it runs, choose what it preloads and decide which modes a user can reach. The actions, actor_key and master_check you leave out take their value from the domain. See Domain DSL.

identity

Names the form. MishkaGervaz.Resource.Info.Form.component_id/1 returns the name. The page that mounts the form chooses the component id. It sits at mishka_gervaz.form.identity.

OptionTypeDefaultDescription
nameatomnoneRequired. Unique form identifier.
routeString.tnoneBase route for redirects after save. Gervaz stores it. The built-in form does not redirect with it.
stream_nameatomnonePhoenix stream name. Defaults to the name plus _stream.

source

Sets the actor, the master check and a gate on the whole form. Its entities set the actions, the preloads and the access rules. It sits at mishka_gervaz.form.source.

OptionTypeDefaultDescription
actor_keyatom:current_userAssigns key for current user. Stored in the config. The components take the actor from their current_user assign, and no built-in code reads this key.
master_check(any -> any)noneFunction returning true for master users. fn user -> boolean Stored in the config. The built-in access modules do not call it: they treat a user whose site_id is nil as a master. To change the rule, override master_user?/1 in a custom access module.
restrictedboolean | (any -> any)falseRestricts every mode of the form to master users. A function gets the state.

actions

Maps the form to Ash actions. A form with any field needs all three, on the resource or the domain. It sits at mishka_gervaz.form.source.actions.

OptionTypeDefaultDescription
createatom | {atom, atom}noneThe create action. An atom serves master and tenant users alike. A tuple {master_action, tenant_action} gives each its own. Required on the resource or on the domain.
updateatom | {atom, atom}noneThe update action, in the same two forms. Required on the resource or on the domain.
readatom | {atom, atom}noneThe read action that fetches the record in edit mode, in the same two forms. Required on the resource or on the domain.

preload

Relationships the form loads, in three tiers. It sits at mishka_gervaz.form.source.preload.

OptionTypeDefaultDescription
alwayslist(atom | {atom, atom})[]Relationships to preload in every mode, as atoms or {source, alias} tuples. The read action of a preloaded relationship must not set pagination required?: true, because preloads pass no limit. Use required?: false.
masterlist(atom | {atom, atom})[]Extra preloads for master users, in the same two forms.
tenantlist(atom | {atom, atom})[]Extra preloads for tenant users, in the same two forms.

access

Gates whether a mode is reachable. A denied mode leaves the form without fields. It sits at mishka_gervaz.form.source.access.

Call: access mode \\ nil, condition \\ nil

Arguments:

ArgumentTypeDefaultDescription
mode:create | :update | (any, any -> any)noneThe mode this rule gates, :create or :update. A function fn mode, state -> boolean in this place is a global gate for both modes.
conditionboolean | (any -> any) | (any, any -> any)noneThe rule for the mode: a boolean or fn state -> boolean. false closes the mode for everyone. A function of two arguments in this place is not evaluated, and the mode stays open.

Options:

OptionTypeDefaultDescription
restrictedbooleanfalseRestrict this mode to master users.

The four calling styles:

CallMeaning
access :create, restricted: trueOnly master users reach the mode.
access :update, fn state -> state.master_user? endA rule for one mode.
access fn mode, state -> mode == :update endOne rule for both modes.
access :update, falseCloses the mode for everyone. Its actions need not exist.