chrisdel101
I have a Role like this in DB. It is attached to both a organization and a employee. But I cannot get both fields organization_id && employee_id to populate. This what it looks like after inserting an employee and an organization.
id | name | value | organization_id | employee_id |
----+-------+-------+-----------------+-------------+-
21 | owner | 1 | | 24 |
Modeling
schema "employees" do
has_many :roles, Role
schema "organizations" do
has_many :roles, Role
schema "roles" do
belongs_to :employee, Employee, foreign_key: :employee_id
belongs_to :organization, Organization, foreign_key: :organization_id
create table(:roles) do
add :organization_id, references(:organizations)
add :employee_id, references(:employees)
The problem is not with the modelling but with the actual insertion.
Here what I’ve tried but it’s not working. I always get the table at the top w/ a missing FK.
I try to
- associate the employee with the role then update the employee,
- associate the role itself with an organization and then update the org.
- Missing: associating the org with the role and upate the org.
Note: this is a bunch of random stuff trying to make the associations take. I know it’s not pretty.
def register_and_preload_employee(attrs) do
# build a role instance
role = Role{
name: "owner",
value: "1"
}
# build employee changeset
emp_changeset = Employee.registration_changeset(%Employee{}, attrs)
# assoc role with employee
emp_changeset = Ecto.Changeset.put_assoc(emp_changeset, :roles, [role])
#role is inserted
# Ecto.Changeset<
# action: nil,
# changes: %{
# email: "...
# ...
# roles: [
# #Ecto.Changeset<action: :insert, changes: %{}, errors: [],
# data: #Role<>, valid?: true>
# ]
# },
# errors: [],
# data: #Employee<>,
# valid?: true
# >
# get org and build_assoc foreign key
organization_id = 1
# get org and preload roles
organization = Company.get_organization(organization_id) |> Repo.preload(:roles)
# ATTEMPT to build assoc with org and role
role_w_org = Ecto.build_assoc(organization, :roles, role)
# org is loaded into role
# %Role{
# __meta__: #Ecto.Schema.Metadata<:built, "roles">,
# id: nil,
# name: "owner",
# value: "1",
# employee_id: nil,
# employee: #Ecto.Association.NotLoaded<association :employee is not loaded>,
# organization_id: 1,
# organization: #Ecto.Association.NotLoaded<association :organization is not loaded>,
# inserted_at: nil,
# updated_at: nil
# }
# insert employee
case Repo.insert(emp_changeset) do
{:ok, new_emp} ->
#preload in case required
emp_preload =
Repo.preload(new_emp, :organizations)
|> Repo.preload(:roles)
# ATTEMPT build assoc with org and role
role_loaded = Ecto.build_assoc(emp_preload, :roles, role_w_org)
# both foreign keys here
# %TurnStile.Role{
# __meta__: #Ecto.Schema.Metadata<:built, "roles">,
# id: nil,
# name: "owner",
# value: "1",
# employee_id: 24,
# employee: #Ecto.Association.NotLoaded<association :employee is not loaded>,
# organization_id: 1,
# organization: #Ecto.Association.NotLoaded<association :organization is not loaded>,
# inserted_at: nil,
# updated_at: nil
# }
# try to update role via employee update - role_loaded is not holding
update = update_employee(emp_preload) #-> Repo.update(...)
#AND/OR
# try to update role via organization update since it's preloaded
update_organization(organization) #-> Repo.update(...)
end
end
I guess maybe my issue is not understanding where the “child” actually gets inserted (not just in elixir, but in any FK relationship). Since the child Role is not actually inserted by me.
Trending in Questions
Hey guys,
I’ve got a huge CSV ( around 10 GB ) that needs to be processed hourly
Do you guys have any suggestions what is the best prac...
New
Hello!
Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app.
I creat...
New
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
So my question is quite simple and i have found no conclusive answer on forum, google or AI.
Should we use :erlang.float for Integer to ...
New
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New
I’m trying to set up Emacs with elixir-ls via lsp-mode and credo via Flycheck. This should mostly be preconfigured as Flycheck picks up c...
New
Other Trending Topics
I am happy to introduce the very α version of the new programming language compiled to BEAM.
Welcome Cure.
It has literally three kille...
New
Hobbes is a low-level distributed database for the Elixir programming language.
Hobbes provides a simple, safe, and scalable storage lay...
New
Hi there! We created Gust: A task orchestrator inspired by Airflow.
For those who have never heard about Aiflow, it’s a Python-based wor...
New
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve.
They are GUI (Emerge) and State management (S...
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
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #blog-post
- #elixirconf-us
- #elixir-ls
- #ai
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming










Showing Posts 1 to 7- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
al2o3cr
What do you mean by “
role_loadedis not holding” here? There’s no connection betweenemp_preloadandrole_loaded.It’s hard to say with certainty without the code for these, but neither one takes
role_loadedas an argument so it’s not going to have an effect on them.What happens if you do
Repo.insert(role_loaded)?chrisdel101
It all comes down to this:
I don’t really understand how the associated object gets inserted. I don’t have a
Repo.insert(role)manually anywhere (other than than the one U just suggested).Repo.insert(role_loaded)does fix the issue sort of. But if I leave everything else as it I end up w this after: 2 instances of the same role.Basically the organization is already inserted and I need to fetch it, and add the role. While the employee is being created here along with the role.
Since this is so hard to do I’ll prob remove the 2nd foreign key constraint
organization_idand just add this manually to Role and have no connection to Organization.jswanner
One thing I don’t have a good sense of in your situation is what data is user provided (and therefore untrusted) or application provided, especially when it comes to roles (
nameandvaluefields). If the data is user provided and you’ll want to repopulate a form if a changeset is invalid, then you’ll most likely want to use cast_assoc/2 to set theroleson the employee, otherwise put_assoc/3 can be used.al2o3cr
There’s no need to give up, things aren’t THAT bad!
You will always get better results with questions about Ecto if you are specific about what you are trying to do. In particular, this is important:
This specific task is alternatively phrased as “I want to insert an employee and also create a role associated to an existing organization”, which then translates to Ecto operations:
You might also refactor this to make
Employee.registration_changesettake anOrganizationand do theput_assocthere, to keep things tidy.GazeIntoTheAbyss
How are you actually trying to insert the data?
If the process involves the creation of the employee then its pretty easy as you already have acess to their id in the process. Create a form with a dropdown/text input for the organisation_id in the employee creation form. Obviously display the name if its a dropdown rather than an ID.
For the organisation_ids, if they already exist and you want a selector for them you need to figure out the new way of doing something like this:
When you create the employee, do so in a case statement like this. You can take the organisation_id from the params, then after the employeee is created you can get the employee’s ID alongside the the organisation_id and just create a new role
Its just a basic example as I don’t know what kind of params you want the employee to have, but if you do this you can access the organisation_id from the form and you can access the newly created employees ID from the {:ok, employee}
The only other step is to add them as cast values in your changeset
chrisdel101
After running this I’m still missing theorganization_idlike the table in the original post shows. Maybe I have it wrong - when I createOrganizationbefore this (getting passed in asorganizationhere) there is noRoleassociated with it. I guess that is wrong.Or is the linerole = Ecto.build_assoc(organization, :roles, name: "owner", value: "1")supposed to handle this?Updated: The issue was that I was using using
build_assocon anOrganizationstruct from before it was inserted i.e not usingRepo.get(), so it was not associated with an existing record. Seems to be working now!chrisdel101
Yes! Using @jswanner solution which is the same as yours I got it to work.
I was not associating it properly with the organization. I have an idea how this associated insert works now.
A brief outline of how it works for my own future reference:
organization(parent 1) and insert into DB.organization(usingRepo.get()) to a create employee functionbuild_assocto link arole(child) with theorganizationemployee(parent 2) with a changesetput_attrto link therolewith theemployeerolewas linked to theorganizationbefore, now all 3 are linkedemployeeandrolewill automatically be inserted, and have both FKs.Thanks @al2o3cr !!