yanniskatsaros

yanniskatsaros

Insert a record using Ecto with a belongs_to association field

Hello! :wave: Relatively new to Elixir, and brand new Phoenix LiveView & Ecto user here.

(Using: Elixir 1.17.1 and Phoenix LiveView 1.0.0-rc.6.)

At a high level, my question boils down to:

How can I insert/create a new record in the database using Ecto when one of the schema fields is a belongs_to association, and the given value already exists in the database?

Please see the code provided below for the full context, but I’d like to be able to create a new user by providing an existing organization, not create a new associated organization.

I have run the Phoenix authentication generator for LiveView (mix phx.gen.auth) and am in the process of making tweaks to the generated schema to suit my project needs. Namely, I have the following simple structure:

  • an organization can have many users associated with it
  • a user can only belong to a single organization

I have mapped these relationships out using the following two modules (I have omitted other functions in each module for brevity):

The users schema (this is what was generated from mix phx.gen.auth and has been modified for my requirements):

# lib/example/accounts/user.ex

defmodule Example.Accounts.User do
  use Ecto.Schema
  import Ecto.Changeset

  @primary_key {:id, :binary_id, autogenerate: true}
  @foreign_key_type :binary_id

  schema "users" do
    field :email, :string
    field :password, :string, virtual: true, redact: true
    field :hashed_password, :string, redact: true
    field :current_password, :string, virtual: true, redact: true
    field :confirmed_at, :utc_datetime

    belongs_to :organization, Example.Accounts.Organization

    timestamps(type: :utc_datetime)
  end
end

The organizations schema:

# lib/example/accounts/organization.ex
defmodule Example.Accounts.Organization do
  use Ecto.Schema
  import Ecto.Changeset

  @primary_key {:id, :binary_id, autogenerate: true}
  @foreign_key_type :binary_id

  schema "organizations" do
    field :name, :string
    field :active, :boolean, default: true
    has_many :users, Example.Accounts.User

    timestamps(type: :utc_datetime)
  end
end

This is how I’ve currently solved the issue, but I feel like it’s unnecessary to first query the Organization simply as a way to use it in the User for the Repo.insert() changeset (since I already have the organization UUID)

# (simplified example)

def register_user(attrs) when is_map(attrs) do
  # example `attrs`
  # %{"email" => "name@example.com", "organization_id" => "7051b9fd-cb24-41ba-b5ca-79cd257612ff", "password" => "[FILTERED]"}
  organization = get_organization!(attrs["organization_id"])

  %User{organization: organization}
  |> cast(attrs, [:email, :password])
  |> validate_required([:organization])
  |> validate_email(opts)
  |> validate_password(opts)
  |> Repo.insert()
end

This approach works but I’m not sure it’s the recommended approach for this pattern. Can someone please help point me in the right direction or offer some advice on the canonical way to achieve this (if this is not correct)? Thanks so much in advance!

Marked As Solved

Hermanverschooten

Hermanverschooten

the belongs_to adds a organization_id field to your schema, you can just cast that.

Also Liked

muelthe

muelthe

Hey there, welcome! If I understand what you’re aiming at, the docs here should give you a good starting point: Associations — Ecto v3.14.0

And maybe more specific: Associations — Ecto v3.14.0

Where Next?

Popular in Questions Top

Kurisu
For example for a current url like http://localhost:4000/cosmetic/products?_utf8=✓&query=perfume&page=2, I would like to get: ...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
JeremM34
Hello, how can I check the Phoenix version ? Thanks !
New
johnnyicon
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
Fl4m3Ph03n1x
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
earth10
Hi, I’m just starting to build a side-project with Elixir and Phoenix and doing some basic test with Elixir alone. What strikes me is th...
New
ycv005
I have followed this StackOverflow post to install the specific version of Erlang. And When I am running mix ecto.setup then getting fol...
New
JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
PeterCarter
There are pre-rolled solutions for other frameworks that do work. However, Phoenix does not seem to have these. Have people had good expe...
New

Other popular topics Top

senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
mcarvalho
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
Nvim
Anybody knows a comprehensive comparison of Django and Phoenix, thanks for the help. Where are they similar? Where do they differ the m...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New
JeremM34
Hello, how can I check the Phoenix version ? Thanks !
New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1144 53690 245
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
sergio
Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browse...
New

Latest on Elixir Forum

Elixir Forum

We're in Beta

About us Mission Statement