Validations based on external data


#1

Hello. I have a validation that relies on some external data. Imagine we’re validating the creation of a meeting room booking, where every user has a maximum duration they are allowed.

I want to check the provided user_id belongs to someone who exists, and then that the duration is below their configured maximum. For example:

Dry::Validation.Form do
  required(:user_id).filled
  required(:duration).filled(:int?)

  validate(valid_user: %[user_id]) do |user_id|
    !User.find(user_id).nil?
  end

  validate(valid_duration: %[user_id duration]) do |user_id, duration|
    user = User.find(user_id)
    duration < user.max_duration
  end
end

Is there a good way to avoid calling User.find twice? This is actually a call to an HTTP API, so it would be great if I could reduce this to just one call. Thanks!


#2

Having thought about it a bit more, could I write a validate method that depends on another validate method? For example:

  validate(valid_user: %[user_id]) do |user_id|
    !User.find(user_id).nil?
  end

  validate(valid_duration: %[valid_user]) do |valid_user|
    duration < valid_user.max_duration
  end

#3

Normally, dependencies and configuration options are passed through with, see examples here: http://dry-rb.org/gems/dry-validation/custom-validation-blocks/

schema = UserSchema.with(ids: [1, 2, 3])

#4

That makes sense, thanks: but what about when those dependencies depend on something that is based on the data being validated, such as the user_id in my example.

I’d like to be able to have the UserSchema validate that the user_id is present, and if it is, then other parts of the data need to be validated based on the result of User.find(user_id). Hopefully that makes sense.