benonymus
How to get team name based on team id in an entity from another table?
Hey I have a user entity in my postgres database and I am displaying it with the generated index method:
def index(conn, _params) do
users = Web.list_users()
render(conn, "index.html", users: users)
end
I have a field in it called teamid that is based on a selected team when the user is created.
how could i get the team name from another table based on the teamid? when i log out the user it looks like this:
[
%Userteam1.Web.User{
__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
id: 6,
inserted_at: ~N[2018-08-11 07:29:21.552256],
name: "ssd",
password: "dssd",
teamid: "1",
updated_at: ~N[2018-08-11 07:29:21.557296]
},
%Userteam1.Web.User{
__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
id: 7,
inserted_at: ~N[2018-08-11 07:30:25.431934],
name: "kkjkj",
password: "kjkjjk",
teamid: "2",
updated_at: ~N[2018-08-11 07:30:25.436358]
},
%Userteam1.Web.User{
__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
id: 8,
inserted_at: ~N[2018-08-11 07:42:05.148300],
name: "tr",
password: "tr",
teamid: "2",
updated_at: ~N[2018-08-12 06:07:00.772189]
}
]
Marked As Solved
Ryzey
I have fixed the web part of the app in my forked version.
- I updated the web schemas with the changes I made earlier to the other schemas (I didn’t realize at first that your use of duplicate schemas was intentional);
- I updated
list_users/0to preload theteamsfield; - Updated any display of
teamidin the templates toteam.name - Updated the
<select>element for team to referenceteam_id
It seems to be working well.
EDIT: Note that even if you want to use 2 schemas for User and 2 schemas for Team, each should still only have one migration as the duplicate schemas will be referencing the same db table. Currently you seem to have 2 migrations for each.
Also Liked
Ryzey
If Ecto knows about how the two schemas are associated, then it will be able to automatically join the tables in queries when you include a preload instruction.
So, if you:
- Add
has_many(:users, Userteam1.User)to your team schema; - Add
belongs_to(:team, Userteam1.Team)to your user schema; - Remove the
teamidfield from the user migration; - Add
add(:team_id, references(:teams))to your user migration; - Replace
:teamidin your user changesetcastandvalidate_requiredparams to:team_id
then you should be able to get all users with team names as follows:
from(User, preload: [:team])
|> Repo.all()
I haven’t tested this code, so it’s not guaranteed to work, but it should point you in the right direction.
Ryzey
Note that you should only have one schema module for User and one for Team, so somehow these have been duplicated in your project (maybe by running the generators twice?). Your migrations are duplicated as well. It will be simpler to have the migration for Team run before the migration for User as one of the fields in User relies on the Team table existing (otherwise you will need a third migration that amends the User table after the Team table has been created). You can try to delete the duplicate files, or maybe it’s easier to start again?
If your user is setup like this:
defmodule Userteam1.User do
use Ecto.Schema
import Ecto.Changeset
schema "users" do
field(:name, :string)
field(:password, :string)
field(:role, :string)
belongs_to(:team, Userteam1.Team)
timestamps()
end
def changeset(user, attrs) do
user
|> cast(attrs, [:name, :password, :role, :team_id])
|> validate_required([:name, :password, :role, :team_id])
end
end
then it will have a team and team_id field:
iex(1)> %Userteam1.User{}
%Userteam1.User{
__meta__: #Ecto.Schema.Metadata<:built, "users">,
id: nil,
inserted_at: nil,
name: nil,
password: nil,
role: nil,
team: #Ecto.Association.NotLoaded<association :team is not loaded>,
team_id: nil,
updated_at: nil
}
and if your team is setup like this:
defmodule Userteam1.Team do
use Ecto.Schema
import Ecto.Changeset
schema "teams" do
field(:name, :string)
has_many(:users, Userteam1.User)
timestamps()
end
def changeset(team, attrs) do
team
|> cast(attrs, [:name])
|> validate_required([:name])
end
end
then it will have a users field:
iex(2)> %Userteam1.Team{}
%Userteam1.Team{
__meta__: #Ecto.Schema.Metadata<:built, "teams">,
id: nil,
inserted_at: nil,
name: nil,
updated_at: nil,
users: #Ecto.Association.NotLoaded<association :users is not loaded>
}
For this to work with the db, your migration for users should look like this (provided the migration for teams is before the migration for users, otherwise you will need to have two migrations for users with an alter table instruction in the second one):
defmodule Userteam1.Repo.Migrations.CreateUsers do
use Ecto.Migration
def change do
create table(:users) do
add(:name, :string)
add(:password, :string)
add(:role, :string)
add(:team_id, references(:teams))
timestamps()
end
end
end
I forked your project on Github, made the changes above, and it worked okay.
dimitarvp
Meaning what exactly? Does not the excellent Ecto documentation help?
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









