sinatra-param icon indicating copy to clipboard operation
sinatra-param copied to clipboard

Question about expected behaviour of `any_of`, `one_of` and `any_all_or_none_of`

Open titoine54 opened this issue 2 years ago • 0 comments

Hello! Here's my use case:

Let's say I have a GET /users route that accepts 3 parameters to filter a list of users from a database. All parameters are not required:

  • param: name String
  • param: age Integer
  • param: is_active Boolean

But, I want to force the client to have a least 1 filter parameter, so I use:

any_of :name, :age, :is_active

The client wants to get all inactive users (of any name and age), so they send a request with a single parameter: is_active: false.

This will result in sinatra-param throwing an error like this:

    "status": "error",
    "details": "Invalid '[\"name\", \"age\", \"is_active\"]' param",
    "class": "Sinatra::Param::InvalidParameterError",
    "message": "One of parameters [name, age, is_active] is required",

This seems to occur because false does not respond to .empty?, in the definition for blank? in lib/sinatra/param.rb and therefor does not count as an existing parameter in the query:

...
    def validate_any_of!(params, names, options)
      raise InvalidParameterError, "One of parameters [#{names.join(', ')}] is required" if names.count{|name| present?(params[name])} < 1
    end
...
    # ActiveSupport #present? and #blank? without patching Object
    def present?(object)
      !blank?(object)
    end

    def blank?(object)
      object.respond_to?(:empty?) ? object.empty? : !object
    end
...

A boolean parameter set to false does not "count" as a valid parameter provided for the routes that use any_of, one_of and any_all_or_none_of. Is this the expected behaviour?

Am I looking at this the wrong way conceptually? Would it make sense to change the logic to accept false as a "valid" parameter value?

Thanks

titoine54 avatar Nov 29 '23 21:11 titoine54