Ecto recursive(nested) cast_assoc

Given a schema structure:

  schema "sales_item" do
    field :id
    field :product_id
    field :parent_id

    belongs_to :parent, SalesItem, foreign_key: :parent_id
    has_many :children, SalesItem, foreign_key: :parent_id
  end

A product can have many children recursively, i.e. each child can have many children.

And input data as follow

children = [
  {
    "product_id": 12197,
    "children": [
      {
        "product_id": 8637,
        "children": [...]
      },
      {
        "product_id": 11224,
        "children": [...]
      },
      {
        "product_id": 3561
      }
    ]
  },
  {
    "product_id": 12200,
    "children": [
      {
        "product_id": 12129,
        "children": [
          {
            "product_id": 11586,
            "children": [...]
          },
          {
            "product_id": 11377
          },
          {
            "product_id": 10682
          }
        ]
      }
    ]
  }
]

If I have to insert this whole linked data in one go into database,

SalesItem.changeset(%SalesItem{}, %{
                    product_id: 1,
                    children: children,
                   })
                   |> Ecto.Changeset.cast_assoc(:children)

What happened was only the first level of children got inserted, the nested children were ignored completely.

Does cast_assoc support nested associations?

1 Like

Does cast_assoc support nested associations?

After having read part of Programming Ecto (Pragmatic Bookshelf), I think that you should dig into Transactions and Multi.
Even if they haven’t explicitly said that cast_assoc doesn’t support nested associations.

The Children.changeset/2 invoked by SalesItem.changeset/2 has to invoke in turnsSalesItem.changeset/2 if the children list of %SalesItem is not empty.

You can use the pattern [_ | _] to match non-empty lists. MADNESS
credit to Dogbert pattern match a non empty list