To write the same SQL you have would be something like:
Repo.all from gur in "group_user_roles",
join: t in "teams", on: t.id == gur.team_id,
join: r in "roles", on: r.id == gur.role_id,
join: u in "users", on: u.id == gur.user_id
That would have the same result of the select, and it does not use any Ecto.Schema. If you have the schemas like:
defmodule GroupUserRole do
schema "group_user_roles" do
belongs_to :user, User
belongs_to :role, Role
belongs_to :team, Team
end
end
defmodule User do
schema ...
end
defmodule Team do
schema ...
end
defmodule Role do
schema ...
end
You can do a simpler query:
Repo.all from gur in GroupUserRole,
join: t in assoc(:team),
join: r in assoc(:role),
join: u in assoc(:user)
I had a different way of solving the same problem. I’m joining users to teams via a many-to-many through, and the through table holds roles and statuses.
schema "users" do
field(:email, :string)
field(:password, Comeonin.Ecto.Password)
field(:verified, :boolean)
many_to_many(
:teams,
Team,
join_through: "users_teams_roles"
)
end
schema "teams" do
field(:name, :string)
many_to_many(
:users,
User,
join_through: "users_teams_roles",
on_replace: :delete
)
has_many(:users_teams_roles, UsersTeamsRoles)
end
schema "users_teams_roles" do
field(:user_id, :id)
field(:team_id, :id)
field(:role, UserTeamRoleType)
field(:status, UserTeamStatusType)
end
And the query would look like:
team_id = 123
user_id = 321
from(
team in Team,
join: user in User,
join: user_team_role in UserTeamRole,
on:
team.id == user_team_role.team_id and
user.id == user_team_role.user_id,
where: user.id == ^user_id and team.id == ^team_id,
select: %{
user_team_role: %{role: user_team_role.role, status: user_team_role.status},
current_user: user,
current_team: team
}
)
|> MyApp.Repo.one()
Sorry I took so long to answer. So basically it was not working for you because I typed my example straight in here and forgot to add the first argument of the assoc as you did. So that’s it, your version is actually the right one
I am looking at a similar setup.
When you would want to show the user their teams, how do you go about that? Do you not miss having user.user_team_role.role and subsequently user.user_team_role.team?
Yeah I guess it’s a little less convenient to access than just have user.team.role… but it’s more flexible. To be honest I forget where I was even using that code so I can’t quite remember how I liked accessing those fields.