Idiomatic way for setting many to many associations

Hello everyone,

I have a User model that has and belongs to many Roles. At some point a form will be submitted to the controller and the association is then set as follows:

def create_user(attrs \\ %{}) do
  roles = Map.get(attrs, "role_ids", [])
  |> Enum.map(&(Repo.get(Role, &1)))
  %User{channels: channels, roles: roles}
  |> User.changeset(attrs)
  |> Repo.insert()
end

I have a hard time believing that this is the way to go about since it’s pretty inefficient, but is is the only way I got it to work. I am sceptical because I need to first select the appropriate role from the database to assign it to the user before it gets inserted into join table.

What is the idiomatic way of populating a has and belongs to many association, given the fact that the required roles already exist?

Thanks!

That is the way to do it if you do not already have the primary key’s for the roles, regardless of the database unless you want to add the lookup to the same query, which you certainly can too.

If you ‘do’ already have the primary keys for the roles then just set it on the necessary tables directly, no need to use the has/belongs/etc stuff at all.

Thanks! Since I already have the primary keys for the roles, I will set them directly on the table itself.

1 Like