I have spent the last 11 days off and on trying to understand the correct way to configure a has_many / belongs_to relationship. I have the schema and migration files correct. The structure has two tables and their names are Group and Testbed. Group has_many Testbeds and each Testbed Belongs_to Group. The problem is that as it stands, I can't choose a pre-existing Tetbed and Group and make the association. I CAN write code that will take a pre-existing group and assign a newly CREATED testbed, but that is not what I want to do. I posted this at Stackoverflow and made some gains. My Stackoverflow question is linked below as well as a wiki doc I am writing to document this process. I believe I might need to use cast_assoc or put_assoc in some way but I am an idiot and don't know exactly how. If it is preferable for me to write out the problem in totality in Discord I will, but the Stackoverflow pretty much has it all and the wiki entry mirrors it. https://stackoverflow.com/questions/77195747/how-to-create-a-simple-association-between-two-tables-in-phoenix-and-submit-the http://elixirblocks.com/index.php?title=Create_Foreign_Key_Relationship_Between_Ecto_Tables
#I am having trouble understanding how to create a foreign key relationship with Ecto
25 messages · Page 1 of 1 (latest)
that SO answer almost looks AI generated, is this starting to be a problem on SO? People using ChatGPT to answer questions instead of answering them themselves?
you have it right, right here:
I've tried to create a testbed and assign it a group_id manually like this:
App.Testbeds.update_testbed(my_testbed,%{group_id: 2,name: "some-name"})
It doesn't affect the group_id and it remains nil.
I am real
you just don't have :group_id listed in your cast function so it ignores it
not you, I meant the person answer on SO
Oh I see
the answer is completely wrong and sounds like AI
@doc false
def changeset(testbed, attrs) do
testbed
|> cast(attrs, [:name, :group_id]) # <- add group_id here
|> validate_required([:name])
end
I just got kicked out of elixirforum going back and forth with someone for 4 hours and I suggested they were gasligting me and then the moderator kicked me out. They never jsut showed me what you just did
I kept asking for a "direct" answer
Let me see if this works, thanks a bunch
huh.... weird...
As far as the console commands to make the association is this still correct:
group = App.Groups.get_group!(1)
testbed = App.Testbeds.get_testbed!(1) Build the association: thing = Ecto.build_assoc(testbed, :group, group) Insert the association into the database using Repo.insert: Repo.insert(thing)
I ran the above code after setting the group_id and I still get this error: `(Ecto.ConstraintError) constraint error when attempting to insert struct:
* "groups_pkey" (unique_constraint)
If you would like to stop this constraint violation from raising an
exception and instead add it as an error to your changeset, please
call unique_constraint/3 on your changeset with the constraint
:name as an option.
The changeset has not defined any constraint.
(ecto 3.10.3) lib/ecto/repo/schema.ex:804: anonymous fn/4 in Ecto.Repo.Schema.constraints_to_errors/3
(elixir 1.14.3) lib/enum.ex:1658: Enum."-map/2-lists^map/1-0-"/2
(ecto 3.10.3) lib/ecto/repo/schema.ex:788: Ecto.Repo.Schema.constraints_to_errors/3
(ecto 3.10.3) lib/ecto/repo/schema.ex:769: Ecto.Repo.Schema.apply/4
(ecto 3.10.3) lib/ecto/repo/schema.ex:377: anonymous fn/15 in Ecto.Repo.Schema.do_insert/4`
no I think
thing = Ecto.build_assoc(testbed, :group, group)
Insert the association into the database using Repo.insert:
Repo.insert(thing)
is incorrect
try this instead:
group = App.Groups.get_group!(1)
testbed = App.Testbeds.get_testbed!(1)
App.Testbeds.update_testbed(testbed, %{group_id: group.id})
but also with change to your changeset function
I have a question. In my app, it appears my associations are working as expected but I feel like there is one loose end. I have preloads used in he list_tables methods in phoenix but I still have a field that says "#ecto.Association.NotLoaded<association " and I am not sure if this is a problem or not. Here is an example: [ %App.Groups.Group{ __meta__: #Ecto.Schema.Metadata<:loaded, "groups">, id: 1, name: "OINK", testbeds: [ %App.TestBeds.TestBed{ __meta__: #Ecto.Schema.Metadata<:loaded, "testbeds">, id: 1, developer: "None", name: "BLURP", owner: "sadasd", note: nil, status: "Available", url: "sdfdsf", version: "asdasd", manager: "ffds", db_backup: false, vnetc_auto_upgrade: false, firmware_auto_upgrade: false, managed_out_of_service: false, firmware_version: nil, group_id: 1, group: #Ecto.Association.NotLoaded<association :group is not loaded>, inserted_at: ~N[2023-10-09 18:02:41], updated_at: ~N[2023-10-09 18:09:03] } ], inserted_at: ~N[2023-10-09 18:00:13], updated_at: ~N[2023-10-09 18:00:13] } ]
It's in the group key near the bottom.
the group has its testbeds association preloaded, but you didn't preload the testbed's group association. This is a pretty normal situation, Elixir doesn't use "references", all structures are values. You can't have the nested testbed refer back to its parent group. You could, if you wanted to, do a nested preload, but I wouldn't suggest that, as you'd just have duplicated data
Thanks, I appreciate it