Zesky665
Question about Contexts and Pivot tables
Hi everyone,
I’m in the process of writing a chat app where a user can be a member of many chat rooms and chat rooms can have many users. I’ve already generated a user schema within the context Account and a room schema within the context Server. And now I’m going to write a schema to connect these two. What I’m wondering is where to put this new schema? Should it be placed outside of the Contexts or should it have it’s own?
Most Liked
kokolegorille
Curiously Yes I can…
I was doing something similar with 2 contexts, Accounting and Social.
This one allows to create, update User
defmodule Chat.Accounting.User do
@moduledoc false
use Ecto.Schema
import Ecto.Changeset
alias __MODULE__
alias Chat.Accounting.Phone
schema "users" do
field :email, :string
field :name, :string
field :password, :string, virtual: true
field :password_hash, :string
has_one :phone, Phone, on_delete: :delete_all
timestamps()
end
@required_fields ~w(name email)a
@registration_fields ~w(password)a
@doc false
# Because of Postgres constraints errors
# You will receive only the first constraint error, not all of them!
def changeset(%User{} = user, attrs \\ %{}) do
user
|> cast(attrs, @required_fields)
|> validate_required(@required_fields)
|> validate_length(:name, min: 1, max: 32)
|> validate_format(:email, ~r/@/)
|> unique_constraint(:name, message: "Name already taken")
|> unique_constraint(:email, message: "Email already taken")
end
@doc false
def registration_changeset(user, attrs \\ %{}) do
user
|> changeset(attrs)
|> cast(attrs, @registration_fields)
|> validate_required(@registration_fields)
|> validate_length(:password, min: 6, max: 32)
|> generate_encrypted_password()
end
# PRIVATE
defp generate_encrypted_password(changeset) do
case changeset do
%Ecto.Changeset{valid?: true, changes: %{password: password}} ->
put_change(changeset, :password_hash, Comeonin.Bcrypt.hashpwsalt(password))
_ ->
changeset
end
end
end
This one allows to manage User association, inside Social context.
defmodule Chat.Social.User do
@moduledoc false
use Ecto.Schema
import Ecto.Changeset
alias __MODULE__
alias Chat.Social.{Group, Post, Comment}
schema "users" do
field :email, :string
field :name, :string
many_to_many :followeds, User,
join_through: "followings",
join_keys: [follower_id: :id, followed_id: :id],
on_delete: :delete_all,
on_replace: :delete
many_to_many :followers, User,
join_through: "followings",
join_keys: [followed_id: :id, follower_id: :id],
on_delete: :delete_all,
on_replace: :delete
many_to_many :groups, Group,
join_through: "subscriptions",
on_delete: :delete_all,
on_replace: :delete
has_many :owned_groups, Group
has_many :posts, Post
has_many :comments, Comment
timestamps()
end
def follow_changeset(%User{} = user, attrs \\ %{}) do
user
|> cast(attrs, [])
|> put_assoc(:followeds, attrs[:followeds])
end
def group_changeset(%User{} = user, attrs \\ %{}) do
user
|> cast(attrs, [])
|> put_assoc(:groups, attrs[:groups])
end
end
As You can see they refer to the same table, but they both represent a User, inside their respective contexts.
Social User cannot be created, they don’t know what a password is, but they can join group, and follow other User as well.
kokolegorille
Another way is to have 2 User schemas, one in Account, one in Server.
Account User would be read/write, Server User would be read only, and used into link to Server context.
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








