Apiepie::ParamErrors Inconsistent interface
wozza35 opened this issue · 9 comments
It is suggested in the documentation to rescue both ParamMissing
and ParamInvalid
exceptions by rescuing from the Apipie::ParamError
superclass. However, the interface of these two sub-classes is different.
For example, I'm trying to return a custom error JSON message in the case of a param error:
rescue_from Apipie::ParamError do |e|
render json: {e.param => 'has an error'}, status: :unprocessable_entity
end
api :GET, '/foo'
param :arg, Array, required: true
def foo
...
ParamMissing#param
returns an instance of Apipie::ParamDescription
, whereas ParamInvalid#param
returns a symbol. So, If the parameter is not an Array:
{
"arg": "has an error"
}
If the parameter is missing:
{
"ParamDescription: site#foo#arg": "has an error"
}
I realize I can rescue the error classes separately or make use of meta programming, but it seems like this might be unintentional behaviour?
I am thinking this might have happened due to a refactor. probably best to update the documentation, unless we're really missing out on something...
Might be related to my change with returning multiple errors, so either we need to reconsider that change or update the documentation.
@davidwessman Can you update the documentation ?
EDIT Now I realized the point about the different interfaces of param
for ParamMissing
vs ParamInvalid
.
So my answer was probably not on point - sorry.
Previous answer
@mathieujobin I reviewed the README and find that it has been updated to this syntax: ```ruby # ParamError is superclass of ParamMissing, ParamInvalid rescue_from Apipie::ParamError do |e| render text: e.message, status: :unprocessable_entity end ```using e.message
instead of e.param
.
@wozza35 Where did you find the e.param
example?
This is my suggestion to handle all the errors, but I am not sure if it should be in the README or not.
rescue_from Apipie::ParamError do |e|
errors = if e.is_a?(Apipie::ParamMultipleMissing)
e.params.to_h {|p| [p.name, "has an error"]}
else
{e.param => "has an error"}
end
render json: errors, status: :unprocessable_entity
end
So it seems like these errors have always used different interfaces for the params.
ParamInvalid
is initialized like:
apipie-rails/lib/apipie/validator.rb
Lines 75 to 77 in 7cc859e
ParamMissing
is initialized like:
apipie-rails/lib/apipie/validator.rb
Lines 41 to 49 in 7cc859e
apipie-rails/lib/apipie/validator.rb
Lines 359 to 368 in 7cc859e
So it seems like it would make sense the change the ParamInvalid
error to receive the whole ParamDescription
as well.
But that seems like breaking change :/
Inconsistent interface isn't ideal, I convey, but considering the little audience of this gem. I'm not sure its worth fixing.
I guess if enough people vote that its worth it. otherwise, I think this is really minor. or at least, I don't see what exact problem is causes.
Hello,
Thanks for your work. I've recently run into this issue. For me the problem it causes is the following:
I'm working on an API that accepts nested params and rescue ParamError
to return a detailed error to the user. I'd like to include the source
attribute described in the JSON API spec. When param
is a ParamDescription
I can used the parent
attribute to reconstruct the parameter's full path. But that's not possible when param
is a String
.
I agree this is a minor issue and I do have a workaround (implementing custom wrapper validators to throw errors with the ParamDescription
). But it's slightly annoying.
Suggestion
Here is my suggestion to implement the change in a (more or less) non-breaking way:
ParamError
may be constructed with either aParamDescription
or aString
.- Errors thrown by Apipie always use a
ParamDescription
. - The
param
attribute is:- Always a
String
. - Always a
ParamDescription
ornil
. - Always the value that was passed to the initializer (so probably a
ParamDescription
). - A
ParamDescription
forParamMissing
, aString
otherwise (ugly but 100% non-breaking).
- Always a
- We add the
param_name
(except in case i.) andparam_description
(except in case ii.) attributes toParamError
.
I'd be happy to submit a PR if one of the proposed options is acceptable.
@PanosCodes Do you have an opinion on the above?
@baarde I think it makes sense, but maybe it would be easier to see some code examples and some tests? Would be great if you could draft something up 🙂