Is it possible to validate associations?

Assuming that I have Upload and Entry schemas, where Upload is associated with Entry with has_many, is it possible to obtain validation results from Entry when calling Upload.changeset?

To illustrate I have defined the following:

defmodule MyApp.Upload do
  # all the imports
  
  schema "uploads" do
    has_many :entries, Entry
  end

  def changeset(upload, attrs \\ %{}) do
    upload
    |> cast(attrs, [])
    |> cast_assoc(:entries, with: &Entry.changeset/2)
  end
end

defmodule MyApp.Entry do
  # imports...
  
  schema "entries" do
    field :name, :string
    field :animal, :string
    belongs_to :upload, MyApp.Upload
  end

  def changeset(entry, attrs \\ %{}) do
    entry
    |> cast(attrs, [:name, :animal])
    |> validate_required([:name, :animal])
  end
end

However, calling

changeset = Upload.changeset(%Upload{entries: %Entry{name: name, animal: animal}})

never seem to actually call Entry.changeset and I can not retrieve validation errors.

What am I doing wrong?

Data in upload is never subject to validation with the exception of validate_required. Only changes pulled in by attrs will be validated.

Does that mean there is no way to validate data being passed to Entry? That seems odd

Sure there is. Pass it with attrs instead of on upload.

I am sorry, I am not sure I understand

It would probably be like this…

changeset = Upload.changeset(%Upload{}, attrs)
1 Like

This?

changeset = Upload.changeset(%Upload{}, %{name: name, animal: animal})

changeset = Upload.changeset(%Upload{}, %{entries: [%{name: name, animal: animal}]})

You’re editing the set of entries on your upload. It needs to be nested and it needs to be a list.

1 Like

Got it! I really appreciate your help guys!