-
Notifications
You must be signed in to change notification settings - Fork 89
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Do not try to coerce "" for numeric & date params #103
base: master
Are you sure you want to change the base?
Conversation
Thanks for putting this up and for the clear explanation of the issue. It is an interesting and kind of unique case. I want to offer an alternative and see what you think about it. One solution that the gem provides that could be helpful here is the
I haven't actually tested this but I suspect it should work because
This isn't a problem for parameters provided in the body, this issue is caused by the fact that all query parameter values are strings. My inclination is not to let the limitations for query parameters change the behaviour for body parameters. Interested in thoughts on this since it is opinionated. @jlw @iMacTia does anything stand out to you that I might be missing? |
Yeah I agree with @ifellinaholeonce, this change might make sense under some circumstances, but it is affectively a breaking change as it changes existing behaviour and could cause unwanted consequences in other use-cases. If there was a clear rule written somewhere where this behaviour is documented as the correct one, then we could consider it. But my understanding on this kind of issues is that there isn't such a rule, only common sense. Interested to know if the |
@ifellinaholeonce and @iMacTia - the suggested workaround does not work since the coerce code - which runs prior to transforms - rescues
The only workaround that I've found for this with rails_param v1.3.1 is the horrid I have put together a sample app (https://github.com/jlw/rails_param_test_app) that shows the current problem I am trying to solve. You can try it out yourself:
It seems to me like the current gem release only works for JSON APIs and HTML forms where all integer, float, date, and/or time values are all required, which seems like an odd set of restrictions. I completely understand having an initial resistance to anything that might introduce a breaking change, but I also don't understand the scenario that you think this change would break. Any required params attempted with an empty string will still be rejected. Have you really seen people write JSON API client-side handlers that provide empty strings for all undefined values? As a user of your gem, who has an endpoint that allows an optional integer param, why would I even care if the request was crafted with Am I missing something? |
When using an HTML form for searching or filtering and a field is left blank, Rails puts an empty string in the params hash, and this raised an unexpected InvalidParameterError when we defined the param as a non-required Integer, Float, Date, etc. Now we will treat that empty string as an un-supplied param and only reject it if the param is flagged as required. - added shared examples for Float tests - nested shared examples in the appropriate scope
315f6e8
to
a4fc380
Compare
Note: after adding the test app last week to show that this affects both GET and POST forms, I have force-pushed my change with improved comments and commit message. |
@jlw you make a very compelling argument and even provided detailed examples, so I can totally see why this is so annoying for folks doing normal Rails forms. On the other hand, APIs are more expressive so we need to be careful about what is possible, what is not, and avoid breaking behaviour folks might be relying on. The scary bit here is interpreting After giving it some thought, I'm not sure I can find a case where a number or date that were passed as blank values and interpreted as @ifellinaholeonce what do you think? |
I don't want to hold this up anymore than I already have. I have my reservations but I don't feel strongly enough to block this. @iMacTia if you're comfortable with it then I say we go for it.
I really like this framing of the change. Thanks for that. I think part of my hesitation for this change comes because the "no-value" doesn't exist for the other type (excluding nil). Special cases always give me pause. I liked that this gem was opinionated and the coercion paths were the same for all the types.
I am certainly guilty of approaching this codebase with a JSON API-first mindset. Thanks for reminding me that that isn't the only usecase.
I've seen consumers of JSON APIs do all sorts of things. I'm not sure this is what we should be making our decision based on. |
Same here, I'm really out of the game when it comes to building forms with Rails, and I appreciate this must be annoying for those folks. I have only one reservation though: this is, in practice, a backwards-incompatible change.
|
Option 3 seems very interesting but likely more complex. Option 2 seems really appealing to me - there have been a couple of threads in this repo where having configs would be helpful. This might be a good opportunity to introduce that pattern to the gem. |
I would advise against option 3 - pushing any kind of request-related metadata down into the coercion logic strikes me as a nasty code smell. If you want to pursue option 2, I'll wait until you have a config pattern in place before refactoring this change. I'm still curious about the assertion that this is a backwards-incompatible change. What examples have you seen in your careers where a JSON client was sending empty strings instead of null values? I've mainly worked with JSON APIs written by large companies and I've never seen anything like that. |
Description
When using an HTML form for searching or filtering and a field is left blank, Rails puts an empty string in the params hash, and this raised an unexpected
InvalidParameterError
when we defined the param as a non-required Integer, Float, Date, etc.Now we will treat that empty string as an un-supplied param and only reject it if the param is flagged as required.
Additional Notes