Validation that tests relationship value (without using custom validator?)

Only two notes:

  1. I’d suggest adding a select statement for only the fields you want from the sprint and
  2. if you want to make this truly resilient to concurrent updates on the sprint’s start date/end date, you could lock the sprint for updates. For this lock to work, however, you’d have to make sure to add before_action?: true when you use this validation, i.e validate YourModule, before_action?: true.

What that would look like:

  def validate(changeset, _, _) do
    sprint = 
     Sprint 
     |> Ash.Query.filter(id == ^Ash.Changeset.get_attribute(changeset, :sprint_id))
     |> Ash.Query.select([:start_date, :end_date])
     |> Ash.Query.lock(:for_update)
     |> Ash.read_one!()

    date = Ash.Changeset.get_attribute(changeset, :date)
    if date < sprint.start_date or date > sprint.end_date do
      {:error, field: :base, message: "activity date must be between the sprint's range of #{sprint.start_date} and #{sprint.end_date}"}
    else
      :ok
    end
  end