Ecto cast_assoc - %UndefinedFunctionError

Will love some advice

Basically i have a map comprising of another nested map.

I am using Ecto.Changeset to cast the values and validate them

   { document: {"id": 2091}, players: ["1", "2"], details: {"code": "100", "id: "saas"}}

    data = %{}
    types = %{document: :map, players: {:array, :string}, details: :assoc}
    details_types = %{code: :string, id: :string}

    changeset =
    {data, types}
    |> Changeset.cast(input, Map.keys(types))
    |> Changeset.cast_assoc(:details, Map.keys(details_types))

But doing this generates an error:

%UndefinedFunctionError{arity: 1, function: :cast, message: nil, module: :assoc, reason: nil}, stack: [{:assoc, :cast, [%{"code" => "100", "id" => "saas"}]

Many thanks

The basic problem here is that you’re defining details to be of type :assoc but :assoc is not a type, unless you defined it somewhere else. Ecto is telling you that it was trying to cast details but it could not find any method called cast in the assoc module. Here’s the list of Ecto types available by default.

If :details is an arbitrary map, then you should use type :map for it. If it has to follow a predefined structure, then I would define a schema for it and turn it into an association. In general, if you’re dealing with complex or nested data structures, it’s easier to work with schemas rather than using inline {data, types} tuples.

1 Like

Hi thanks very much. Apologies but if i assign a type :map to details, i get an error that an :assoc is expected which is why i defined the type as an :assoc.

1 Like

You should show the document schema, and how You set up the association with details…

You should also have a look at embedded schema, and cast embed, as it might be helpful.

1 Like

yes because you’re using cast_assoc, which you can only use if you define an association, but you haven’t defined any. You define an association by declaring a schema and calling has_one, has_many, embeds_one, embeds_many etc.

You should rewrite your code using a schema definition (it doesn’t appear like you’re using any, as you’re working with inline types), and/or explain a bit better what you’re trying to achieve.

I also recommend reading the ecto schema docs.