Hi,
I want to set an attribute based on a relation.
In the concrete example:
create :create do
primary? true
accept [:content, :task_id]
change relate_actor(:user)
change set_attribute(:workgroup_id, <<THE WORKGROUP THE USER BELONGS TO>>)
end
I would like not to have to pass workgroup_id
as an argument since it can be derived from the user
/actor
+ task_id
. A user can be in many workgroups in an organization, and the task
is associated with exactly one organization.
I need to store the workgroup_id
, since in the system a user can change organizations and it is important that we know which org the item was created for, we cannot rely on looking it up through the user after the point of creation.
In this case, you’d do this with a custom change.
create :create do
primary? true
accept [:content, :task_id]
change relate_actor(:user)
change fn changeset, context ->
Ash.Changeset.before_action(changeset, fn changeset ->
actor = context.actor
task = Ash.Changeset.get_attribute(changeset, :task_id)
workgroup_id = # look up the workgroup id
Ash.Changeset.force_change_attribute(changeset, :workgroup_id, workgroup_id)
end
end
end
A small note, I’ve shown the inline anonymous function syntax here for brevity, but the best practice is to define a module to contain this logic.
change YourChange
defmodule YourChange do
use Ash.Resource.Change
def change(changeset, _opts, context) do
actor = context.actor
task = Ash.Changeset.get_attribute(changeset, :task_id)
workgroup_id = # look up the workgroup id
Ash.Changeset.force_change_attribute(changeset, :workgroup_id, workgroup_id)
end
end