How do you set an attribute to the join resource when creating?

For example, I have a User and an Org, joined by a many_to_many through a Join Resource UserOrg. UserOrg has an attribute :role. How do I set the role on the UserOrg when creating an Org?
create :create do
accept [:name]
argument :user_id, :binary

change fn changeset, %{actor: actor} = _context ->
changeset |> Ash.Changeset.set_argument(:user_id, actor.id)
end

change manage_relationship(:user_id, :users, type: :append_and_remove)
# ^^^ somehow set :role to :owner in this relationship
end
create :create do
accept [:name]
argument :user_id, :binary

change fn changeset, %{actor: actor} = _context ->
changeset |> Ash.Changeset.set_argument(:user_id, actor.id)
end

change manage_relationship(:user_id, :users, type: :append_and_remove)
# ^^^ somehow set :role to :owner in this relationship
end
11 Replies
ZachDaniel
ZachDaniel•3y ago
Ash HQ
Module: Ash.Changeset
View the documentation for Ash.Changeset on Ash HQ.
ZachDaniel
ZachDaniel•3y ago
There is a format for determining which fields get sent to the join table although, FWIW, in your case you could just manage the join relationship directly
accept [:name]
change fn changeset, %{actor: actor} = _context ->
changeset
|> Ash.Changeset.manage_relationship(:users_join_relationship, %{
user_id: actor.id,
role: :owner
})
end
accept [:name]
change fn changeset, %{actor: actor} = _context ->
changeset
|> Ash.Changeset.manage_relationship(:users_join_relationship, %{
user_id: actor.id,
role: :owner
})
end
Arjun Bajaj
Arjun BajajOP•3y ago
No such relationship users_join_relationship for resource Org I tried with users_join_assoc too, but then it sets that to an empty list.
ZachDaniel
ZachDaniel•3y ago
ah, yeah sorry it should be users_join_assoc ah, perhaps it needs to be a list not a map? you should be able to manage it that way though oh my example didn't have any options
change fn changeset, %{actor: actor} = _context ->
changeset
|> Ash.Changeset.manage_relationship(:users_join_relationship, [%{
user_id: actor.id,
role: :owner
}], type: :append_and_remove)
end
change fn changeset, %{actor: actor} = _context ->
changeset
|> Ash.Changeset.manage_relationship(:users_join_relationship, [%{
user_id: actor.id,
role: :owner
}], type: :append_and_remove)
end
Arjun Bajaj
Arjun BajajOP•3y ago
With :append_and_remove it gives an error record with role: :owner | user_id: "EF6DF726A6" not found. However, with :create instead, it gives this error: Input invalid: relationship user is required. I'm guessing this is complaining that the user on the join resource is not provided through here.
ZachDaniel
ZachDaniel•3y ago
oh, yeah type: :create
Arjun Bajaj
Arjun BajajOP•3y ago
That doesn't work either Input invalid: relationship user is required.
ZachDaniel
ZachDaniel•3y ago
I assume on the join resource you have belongs_to :user, ... set attribute_writable? true on the belongs_to relationships
Arjun Bajaj
Arjun BajajOP•3y ago
that works! 🚀 For future readers, after setting attribute_writable? true on your join resource association, here's the final create function which works:
create :create do
accept [:name, :desc]
argument :user_id, :binary

change fn changeset, %{actor: actor} = _context ->
join = %{user_id: actor.id, role: :owner}
changeset |> Ash.Changeset.manage_relationship(:users_join_assoc, join, type: :create)
end
end
create :create do
accept [:name, :desc]
argument :user_id, :binary

change fn changeset, %{actor: actor} = _context ->
join = %{user_id: actor.id, role: :owner}
changeset |> Ash.Changeset.manage_relationship(:users_join_assoc, join, type: :create)
end
end
Thanks a lot for all your help @Zach Daniel! :ashley:
ZachDaniel
ZachDaniel•3y ago
You probably don’t need the user_id argument anymore
Arjun Bajaj
Arjun BajajOP•3y ago
Yes, thanks!

Did you find this page helpful?