tnederlof
Self Referencing many_to_many Updating Associations Issues
EDIT ** The code now works after some help
I started a thread a few days ago with some general questions and since I am now focused and have some running code I thought it would make sense to post fresh with more direct questions.
I have Users which can have friendships and the converse of that is a reverse_friendship using the Friendships table (many_to_many relationships). My attempted code is below but I am having 2 problems.
- how to add the associations with timestamps. If I don’t add timestamps to the table in the Friendship migration the inserts run fine
- put_assoc works (User 1 has User 2 as a friend and User 2 has User 1 as a reverse friend). However when I go to add another I get a warning about on_replace, I think thats because put_assoc is essentially trying to overwrite the entire friends/reverse friends. How can I add friend/reverse_friend associations and have it be additive (Add User 2 then User 3, etc to User 1 as a friend).
User Schema
defmodule App.Users.User do
use Ecto.Schema
import Ecto.Changeset
schema "users" do
field :name, :string
field :phone_number, :string
field :username, :string
field :email, :string, null: false
many_to_many :friends, User,
join_through: "friendships",
join_keys: [from_user_id: :id, to_user_id: :id]
many_to_many :reverse_friends, User,
join_through: "friendships",
join_keys: [to_user_id: :id, from_user_id: :id]
timestamps()
end
@doc false
def changeset(user_or_changeset, attrs) do
required_fields = [:username, :name, :email, :phone_number]
user_or_changeset
|> cast(attrs, required_fields)
|> validate_required(required_fields)
end
end
User Migration
defmodule App.Repo.Migrations.CreateUsers do
use Ecto.Migration
def change do
create table(:users) do
add :name, :string, null: false
add :username, :string, null: false
add :email, :string, null: false
add :phone_number, :string, null: false
timestamps()
end
create unique_index(:users, [:username, :email, :phone_number])
end
end
Friendship Schema
defmodule App.Users.Friendship do
use Ecto.Schema
alias App.Users.User
import Ecto.Changeset
@primary_key false
schema "friendships" do
belongs_to :from_user, User
belongs_to :to_user, User
timestamps()
end
end
Friendship Migration
defmodule App.Repo.Migrations.AddCreateFriendshipTable do
use Ecto.Migration
def change do
create table(:friendships, primary_key: false) do
add :from_user_id, references(:users)
add :to_user_id, references(:users)
add :accepted, :boolean, default: false
timestamps()
end
create unique_index(:friendships, [:from_user_id, :to_user_id])
end
end
Users Context Module
defmodule App.Users do
import Ecto.Query, warn: false
alias App.Repo
alias App.Users.User
alias App.Users.Friendship
def add_friend(user, friend_user) do
%Friendship{}
|> change()
|> put_assoc(:from_user, user)
|> put_assoc(:to_user, friend_user)
|> Repo.insert()
end
end
Marked As Solved
fuelen
- You have to define a
Friendshipschema and use it inmany_to_manyassociation instead of direct table name. Timestamps will be added automatically if you useRepo.insertorRepo.insert!, but if you want to useRepo.insert_allthen values for timestamps must be provided manually. put_assocmanages the whole collection. InsertFriendshiprecord this way:
def add_friend(user, friend_user) do
%Friendship{}
|> change()
|> put_assoc(:from_user, user)
|> put_assoc(:to_user, friend_user)
|> Repo.insert()
end
*tip: add unique composite index for from_user_id and to_user_id fields.
2
Popular in Questions
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
Hi,
I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
Hello, how can I check the Phoenix version ?
Thanks !
New
Could someone help me? I’m making my first elixir program, number guessing game. I can’t figure out how to convert the user’s guess from ...
New
Hi all,
I’ve just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage.
I’m trying to use Postgres...
New
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: )
Hello all, this is ...
New
Hi all,
Trying to get some more clarity over utc_datetime and naive_datetime for Ecto:
The documentation above suggests that while ...
New
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar.
I p...
New
Hi everyone,
I was playing with phoenix liveView but I run into an issue. I have a form and want to validate each input text when the te...
New
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New
Other popular topics
This post is a wiki (feel free to hit the edit button near the bottom right of this post to add your own changes!)
This post collects co...
New
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
Hi,
I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
Phoenix 1.4.0 released
Phoenix 1.4 is out! This release ships with exciting new features, most notably
with HTTP2 support, improved deve...
New
Hi everyone,
One of the features added to Elixir early on to help integration with Erlang code was the idea of overridable function defi...
New
Using vs code and installed ElixirLS: support and debugger.
And I got an error popped up on start up says
Failed to run ‘elixir’ comma...
New
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this:
...
New
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
New
I’m brand new to Phoenix and I have stripped one of the demo applications to the bone. I just want to get an svg up on the screen. Here i...
New
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









