Allow empty lists for cast embed

I have a schema that uses embeds_many and would like it to also allow for the list to be empty if there is no Actors. e.g.

id: "The Matrix",
actors: []

my schema:

    field(:id, :string, primary_key: true)
    embeds_many(:actors, Actor, on_replace: :delete)
    field(:updated_timestamp, :map)
    field(:updated_at, :utc_datetime)
  end

my changeset:

  def changeset(movie, %{} = params, opts \\ []) do
    now = Keyword.get(opts, :now, DateTime.utc_now())

    movie
    |> cast(params, [
      :id
    ])
    |> cast_embed(:actors, with: &Actor.changeset/2, required: true)
    |> Schema.put_updated_bson_timestamp(now)
    |> Schema.put_updated_at(now)
    |> validate_required(@required_fields)
  end

When supplying required: true to cast_embed and the movie does not have any actors, we get a {:error, "actors can not be blank"}. When taking off the required: true the actors field can be missing completely and it is still valid. Is this an edge case where I would have to write my own validation for the :actors field?

What kind of issue are you running into by keeping it optional?

embeds_many fields have a default of empty list so if they’re not provided they will be set to []. Is there some kind of edge case you’re running into that isn’t working as expected?

i would like to enforce that the field should be there even if it is empty. If required: true is set and the actors list is [] it will say the changeset is invalid because the actors list is empty…

The field will have a default value of [] because it’s an embeds_many. So if you make it optional it won’t raise and it will be set to [] automatically if not there. This should suffice? Or am I mistaken?

When i wrote a test for it and deleted the :actors key from the Movie schema the changeset is still valid but my intentions is for the changeset to not be valid when the :actors key is missing. It should still be valid when actors is a empty list though.

Keeping it optional will allow for the key to not be there at which is not what i am after. However using the require: true i am not able to leave the list as empty as it detects it is empty

Oh ok I think I see now. You want to protect against someone manually overwriting it to nil? You won’t be able to do it with cast_embed so you’ll have to make your own function. You can use get_field to see if it is nil in the changes or the original data.

ahh ok ok ill give it a shot and report back.

Ended up writing my own function to check if the field is included inside of the params and validating it that way.