1

I'm having an issue for an API written with the Grape gem. I've written a custom validator that checks that UUIDs sent to my API match the expected format.

For optional fields, users can either 1. not send the value, or 2. send a null value.

And in that 2nd case, my UUID validator is evaluated and checks against the nil value, which fails (it should succeed since this is an optional param). I'd need to check in my validator if the checked parameter is optional or required, and allow a nil value only if parameter is optional. Do you know any way to do this?

So far the only options I've got is to allow either nil value or matching pattern, for every UUID (which is not safe), or to define two different validators.

module PublicApi
  module Validators
    # This class represents a UUID params and validates the UUID format
    # Valid for both nil values and uuid-formatted strings (8-4-4-4-12)-
    #
    # Usage in the endpoint:
    #   requires :id, type: String, uuid: true
    #
    class Uuid < Grape::Validations::Base
      def validate_param!( attr_name, params )
        # TODO: accept nil value only if the param is optional
        uuid_param = params[ attr_name ]
        unless uuid_param.nil? || uuid_param =~ /^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}$/i
          fail Grape::Exceptions::Validation, params: [ @scope.full_name( attr_name ) ],
                                              message: "must be a UUID, in this format: '58d5e212-165b-4ca0-909b-c86b9cee0111'"
        end
      end
    end
  end
end

If anybody has a solution?

Pierre-Adrien
  • 2,836
  • 29
  • 30

1 Answers1

1

Grape::Validator::Base gives you an instance variable @required. It is a boolean that returns true (requires) or false (optional). You can use this along with the param value to determine if you need to return the method early.

return unless  params[attr_name] && @required

Reference: Grape::Validator::Base docs

Jeremy Caney
  • 7,102
  • 69
  • 48
  • 77
RyanC
  • 11
  • 2