Can't get put_assoc to work with parsed keyword list

I have been struggling with put_assoc for days. It’s taken me awhile to get my head rapped around how to do associations with many-to-many tables when the related join is already created.

I’m presenting a multi-list of “resource types” to the user. They select multiple types and I get back the IDs for the associated table. I just need to make the association between the newly created “resource” and these “resource_types”. That is the join table. But I can’t seem to make this connection with put_assoc. Here is what I’ve got:

PARAMS coming in from form:
PARAMS
%{
“title” => “blah”,
“description” => “blah blah”,
“resource_types” => [“1”, “2”],
}

Here is my RESOURCE changeset that is trying to set the put_assoc for the RESOURCE_TYPES (the many_to_many relationship is set in the schema):

def changeset(resource, attrs) do
resource
|> cast(attrs, [:title, :description])
|> put_assoc(:resource_types, [parse_params(attrs, “resource_types”)])
end

defp parse_params(attrs, assoc_type) do
assoc_list = get_in(attrs, [assoc_type])
formatted_list_map = Enum.map(assoc_list, fn x → {:id, String.to_integer(x)} end)

IO.puts "ASSOC LIST"
IO.inspect(formatted_list_map)
formatted_list_map

end

** So when I print out that ASSOC LIST after all of the formatting it looks like this:
[id: 1, id: 2]. I made sure that I’m returning that formatted_list, so it should be getting passed into put_assoc. **

But I print out the newly created Resource Changeset out and the resource_type IDs are missing!!! And I’m getting an error because they are missing.

CHANGESET:
ecto.Changeset<
action: nil,
changes: %{
description: “blah”,
resource_types: [
ecto.Changeset<
action: :insert,
changes: %{id: 2},
errors: ,
data: project.Resourcetypes.Resourcetype<>,
valid?: true
>
],
title: “blah”
},
errors: ,
data: project.Resources.Resource<>,
valid?: true

Why is put_assoc not taking that keyword list?

I think this part should be like:

Enum.map(assoc_list, fn x -> %{id: String.to_integer(x)} end)

I was studying the Ecto book last night and from I can tell, I can’t just pass it the IDs. I have to actually query the database with those IDs and pull out the ResourceTypes and THEN pass those into the put_assoc. But that is totally inefficient since I’m already holding onto the Resource ID and the Resourcetype ID. That’s all that is needed for the many-to-many table. I’m beginning to think that put_assoc isn’t efficient for all many-to-many situations. Have you run into this?

You can write to intermediary table directly

I was originally writing to the join table directly, but that doesn’t work as smoothly when you are doing LiveView. In order for me to present a form that includes the associated tables (both displaying and gathering associated input), I have to preload those associations. I decided it was easier to use put_assoc and manage the changesets accordingly so that the frontend will work. I’m finding the entire association management very difficult as a new developer in Phoenix/Elixir.