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
cause rails to correctly place optional path parameter booleans #42283
Conversation
1f39826
to
5f57ea5
Compare
@HParker Thank you for your patch! This is interesting because we're changing the behavior and some apps may be indirectly depending upon that. What if you had an optional parameter that you expected to be a boolean? Correct me if I'm wrong but the current behavior would still pass that parameter as |
5f57ea5
to
1033b6a
Compare
Thanks for looking at it @zzak!
Yeah, that is a good point. Until reading your comment I didn't know this was possible, but you can have a route like,
I updated my branch to make This still prevents adding the parameter at the end of the url and makes behavior more consistent. |
Rails also allows to put an optional parameter as a positional argument:
Can you make sure it is also consistent and add tests for that? |
@bogdan Good call, I did not consider positional args 🤦 |
44313bd
to
a8390e4
Compare
Added tests for positional arguments & rebased to one commit. |
d03c499
to
0c64d8d
Compare
@@ -118,7 +118,7 @@ def extract_parameterized_parts(route, options, recall) | |||
end | |||
end | |||
|
|||
parameterized_parts.keep_if { |_, v| v } | |||
parameterized_parts.delete_if { |_, v| v.nil? } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we use compact here?
parameterized_parts.delete_if { |_, v| v.nil? } | |
parameterized_parts.compact! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, compact
works, but compact!
does not. Thanks for the suggestion! either way it is nicer then delete_if
:)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, compact!
only works if you leave the parameterize_parts
line after (because it returns nil
if nothing is removed). compact
will always return the new value because it creates a copy
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see! I suppose delete_if
doesn't create a copy so maybe it would be better to use compact!
and leave the parameterized_parts
at the end. like you originally suggested.
1717221
to
9805b2b
Compare
@kamipo I think this is ready for review if you wouldn't mind taking another look? 🙇 |
previously, if you specify a url parameter that is part of the path as false it would include that part of the path as parameter at the end of the url instead of in the path for example: `get "(/optional/:optional_id)/things" => "foo#foo", as: :things` `things_path(optional_id: false) # => /things?optional_id=false` this is not the case for empty string, `things_path(optional_id: '') # => "/things" this is due to a quark in how path parameters get removed from the parameters. we where doing `(paramter || recall).nil?` which returns nil if both values are nil however it also return nil if one value is false and the other value is nil. i.e. `(false || nil).nil # => nil` which is confusing. After this change, `true` and `false` will be treated the same when used as optional path parameters. meaning now, ``` get '(this/:my_bool)/that' as: :that that_path(my_bool: true) # => `/this/true/that` that_path(my_bool: false) # => `/this/false/that` ``` fixes: rails#42280 Co-authored-by: Ryuta Kamizono <kamipo@gmail.com>
9805b2b
to
98ed240
Compare
cause rails to correctly place optional path parameter booleans
Previously, if you specify a url parameter that is part of the path as false it would include that part of the path as parameter for example:
get "(/optional/:optional_id)/things" => "foo#foo", as: :things
things_path(optional_id: false) # => /things?optional_id=false
this is not the case for empty string,
`things_path(optional_id: '') # => "/things"
this is due to a quark in how path parameters get removed from the parameters.
we where doing
(paramter || recall).nil?
which returns nil if both values are nil however it also return nil if one value is false and the other value is nil. i.e.(false || nil).nil # => nil
which is confusing.After this change,
true
andfalse
will be treated the same when used as optional path parameters. meaning now