Description
The Problem
Validation raises a NoMethodError (undefined method `has_key?' for "not a hash":String) with the following code
Parameters
param :foo, Hash, :desc => "foo description" do
param :bar, String, :desc => "bar description"
end
Note: the example in the documentation would also suffice to cause this error
Then send send request to your server with a body that looks like this:
{
"foo" : "not a hash"
}
Note: sending an array instead of a string causes the same exception
What is expected is that Apipie would raise a validation exception about the parameter not being a hash.
Why it happens?
From what I can tell the hash validator's validate method tries to validate all it's children recursively first before validating itself (if it ever validates itself I cannot tell).
def validate(value)
if @hash_params
@hash_params.each do |k, p|
if Apipie.configuration.validate_presence?
raise ParamMissing.new(k) if p.required && !value.has_key?(k)
end
if Apipie.configuration.validate_value?
p.validate(value[k]) if value.has_key?(k)
end
end
end
return true
end
This loops over the child param definitions from the example above and then checks to see if that child parameter's key exists in the hash (value.has_key?(k)). This is great when the value IS a hash, however when it is not a hash (which is what we are trying to validate) then these 2 lines raise the NoMethodError exception (which line depends on if the method was set to required or not).
raise ParamMissing.new(k) if p.required && !value.has_key?(k)
...
p.validate(value[k]) if value.has_key?(k)
Is it legit?
I plan on trying to fix this but it would be really helpful to know if this is a legit problem.
I am a little skeptical that I am doing it correctly.
I would also like to point out that issue #166 possibly stumbled across the same error however the fix suggested allows validation to finish but will not raise a validation exception at all when the parameter is not a hash (which it should) so we can return status code 422.