defmodule NLdoc.Spec.TableRow do @moduledoc """ This module defines the Ecto schema for the NLdoc spec TableRow object. """ use NLdoc.Spec.Schema, type: "https://spec.nldoc.nl/Resource/TableRow" alias NLdoc.Spec.{TableCell, TableHeader} typed_embedded_schema null: false do field :id, Ecto.UUID field :type, :string, default: @resource_type field(:children, {:array, PolymorphicEmbed}, types: map([TableCell, TableHeader]), type_field_name: :type, on_replace: :delete, default: [], array?: true ) :: [TableCell.t() | TableHeader.t()] field(:descriptors, {:array, PolymorphicEmbed}, types: map(NLdoc.Spec.descriptors()), type_field_name: :type, on_replace: :delete, default: [], array?: true ) :: [NLdoc.Spec.descriptor()] end def changeset(object, attrs) do object |> cast(attrs, [:id, :type], @cast_opts) |> cast_polymorphic_embed(:children, @cast_opts) |> cast_polymorphic_embed(:descriptors, @cast_opts) |> validate_required([:id, :type]) |> validate_inclusion(:type, [@resource_type]) |> validate_has_children(attrs) end def validate_has_children(changeset, attrs) do if at_least_one_element?(attrs[:children]) or at_least_one_element?(attrs["children"]) do changeset else add_error(changeset, :children, "must have at least one element") end end @spec at_least_one_element?(list() | nil) :: boolean() def at_least_one_element?(nil), do: false def at_least_one_element?([]), do: false def at_least_one_element?([_ | _]), do: true end