can someone please guide me for making it functionally working and then write it in better way?
I have a Organization resouce with users many_to_many relationship as below
actions do
update :invite_users do
argument :users, {:array, InviteUser},
allow_nil?: true,
description: "users of organization"
require_atomic? false
change InviteUsers
end
...
end
relations
many_to_many :users, Manwa.Accounts.User do
through Manwa.Orgs.OrganizationUser
source_attribute_on_join_resource :organization_id
destination_attribute_on_join_resource :user_id
end
....
end
defmodule Manwa.Orgs.OrganizationUser do
@moduledoc false
use Manwa.ResourceWIthoutID,
data_layer: AshPostgres.DataLayer,
domain: Manwa.Orgs
....
actions do
defaults [:read, :destroy, create: :*, update: :*]
end
attributes do
attribute :role, Manwa.Accounts.UserRole, primary_key?: true, allow_nil?: false, public?: true
end
relationships do
belongs_to :organization, Manwa.Orgs.Organization,
primary_key?: true,
allow_nil?: false,
attribute_type: :integer
belongs_to :user, Manwa.Accounts.User,
primary_key?: true,
allow_nil?: false,
attribute_type: :integer
end
end
invite user change tries to
- check if user has account in system, if not it creates account and then goes through manage_relationship change.
defmodule Manwa.Orgs.Changes.InviteUsers do
use Ash.Resource.Change
@password_length 16
@impl true
def change(changeset, opts, context) do
map =
Enum.reduce(changeset.arguments.users, [], fn invite, acc ->
case Manwa.Accounts.get_user_by_email(invite.email) do
{:ok, user} ->
acc = [%{user_id: user.id, role: invite.role} | acc]
_ ->
random_password =
@password_length
|> :crypto.strong_rand_bytes()
|> Base.encode64()
|> binary_part(0, @password_length)
{:ok, user} =
Manwa.Accounts.register_with_password(
invite.email,
random_password,
random_password,
actor: context.actor
)
acc = [%{user_id: user.id, role: invite.role} | acc]
end
end)
Ash.Changeset.manage_relationship(changeset, :users, map,
on_lookup: :relate,
join_keys: [:role, :user_id]
)
end
end
Calling the action
Orgs.invite_users(org, %{users: [%{email: "a.com", role: :admin}, %{email: "b.com", role: :admin}]}, actor: super_user )
...
map #=> [
%{role: "admin", user_id: 7308783368152281088},
%{role: "admin", user_id: 7308783365732167680}
]
does not do the manage_relationship part ( does not insert data and changeset is valid)