Dry-validation: Validate entity reference

Hi!

I have an usecase where I need to validate params for a send_notifications HTTP API endpoint which sends push a notification to multiple users. Validation the request payload is easy, but I need to validate also if the referenced users exists, which in this case seems that the approach would be to use rule API.

class SendNotificationContract < Dry::Validation::Contract
  option :user_repo

  params do
    required(:message).filled(:string)
    required(:user_ids).array(:str?)
  end

  rule(:user_ids) do
    existing_user_ids = user_repo.by_ids(value).map(&:id)
    missing_users = value - existing_user_ids

    unless missing_users.empty? do
      key.failure("users #{missing_users.join(', ')} not found")
    end
  end
end

Everything is great if the validation fails. The request fails with proper messages. But the issue is when the validation passes. The next step in the request handling is to send the message to the specified users and to do that I need to get the notification_token for each user from the db, which leads to another db query to fetch that, instead doing it in one db query (fetch the users, find the missing ones, then use the fetched already objects to get that notification_token.

My problem is to find an approach using dry-validation, but not having separate db round trips for the validation step. I’m thinking about writing 2 contracts. One for validating the payload and the second one to define that rule by taking user_ids and users as parameters. What do you think?

Have you seen rules have shared context that also available from the outside? dry-rb - dry-validation master - Rules

I can’t imagine how I missed that. Thanks a lot :smiley:

1 Like