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?