Skip to content
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

Refactor handling of :action default in routing #23103

Merged
merged 1 commit into from
Apr 24, 2016

Conversation

pixeltrix
Copy link
Contributor

The longstanding convention in Rails is that if the :action parameter is missing or nil then it defaults to 'index'. Up until Rails 5.0.0.beta1 this was handled slightly differently than other routing defaults by
deleting it from the route options and adding it to the recall parameters.

With the recent focus of removing unnecessary duplications this has exposed a problem in this strategy - we are now mutating the request's path parameters and causing problems for later url generation. This will typically affect url_for rather a named url helper since the latter explicitly pass :controller, :action, etc.

The fix is to add a default for :action in the route class if the path contains an :action segment and no default is passed. This change also revealed an issue with the parameterized part expiry in that it doesn't
follow a right to left order - as soon as a dynamic segment is required then all other segments become required.

@pixeltrix
Copy link
Contributor Author

@jeremy @tenderlove @rafaelfranca I'd appreciate a sanity check on this please - tests seem to pass but I doubt we have coverage over every permutation.

@pixeltrix pixeltrix self-assigned this Jan 18, 2016
@pixeltrix pixeltrix added this to the 5.0.0 milestone Jan 18, 2016
@pixeltrix pixeltrix force-pushed the refactor-handling-of-action-default branch 2 times, most recently from f716d60 to 3c5eb0b Compare January 23, 2016 14:37
The longstanding convention in Rails is that if the :action parameter
is missing or nil then it defaults to 'index'. Up until Rails 5.0.0.beta1
this was handled slightly differently than other routing defaults by
deleting it from the route options and adding it to the recall parameters.

With the recent focus of removing unnecessary duplications this has
exposed a problem in this strategy - we are now mutating the request's
path parameters and causing problems for later url generation. This will
typically affect url_for rather a named url helper since the latter
explicitly pass :controller, :action, etc.

The fix is to add a default for :action in the route class if the path
contains an :action segment and no default is passed. This change also
revealed an issue with the parameterized part expiry in that it doesn't
follow a right to left order - as soon as a dynamic segment is required
then all other segments become required.

Fixes #23019.
@bquorning
Copy link
Contributor

@pixeltrix Code looks good. I've been patching my Rails 5 app with this PR's code for a while now, and haven't seen any issues. It solves the issues with recall being changed.

@@ -1964,11 +1964,11 @@ def test_generate_extras
def test_extras
params = {:controller => 'people'}
assert_equal [], @routes.extra_keys(params)
assert_equal({:controller => 'people'}, params)
assert_equal({:controller => 'people', :action => 'index'}, params)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calling extra_keys(params) will mutate params, is that correct?

@bquorning
Copy link
Contributor

Just want to mention @schneems , since he was assigned #24438 which would be solved by this PR

end

def action
requirements[:action] || ':action'
parts.include?(:action) ? ':action' : requirements[:action]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Going from constant time to linear here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The number of parts is almost always so low that the speed difference doesn't matter – right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

¯ \ _ (ツ) _ / ¯ I don't remember what parts is right here, if it's a hash we could parts.key?(:action) if it's an array, then maybe when it's initialized we could loop over and pull out those to values :controller and :action so that we only have to iterate once.

The routing code is very performance sensitive. I'm fine with getting a solution on there then working to speed it back up if it's an issue.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's also the routing inspector so doesn't need to be the most performant of code, unlike recognition and generation.

@schneems
Copy link
Member

Thanks for the ping, I subscribed to the issue already. I haven't had the chance to dig into the mutation bug I introduced. I think the approach is sound, the only thing that would worry me is that some existing tests were modified, I'm not clear on the reasons why. @pixeltrix how comfortable are you moving forward with this solution? Are you happy with it or is there more you want to do?

@jeremy jeremy added this to the 5.0.0 milestone Apr 13, 2016
@schneems
Copy link
Member

Ping, any new thoughts or blockers here?

@pixeltrix
Copy link
Contributor Author

@schneems will have another look at this in the next day or two

@jeremy jeremy modified the milestones: 5.0.0.beta4, 5.0.0 Apr 24, 2016
@jeremy
Copy link
Member

jeremy commented Apr 24, 2016

Let's nail this down so we get a beta4 out.

@jeremy
Copy link
Member

jeremy commented Apr 24, 2016

I'm puzzled that we didn't simply revert 1993e2c. This PR checks out, though. Merging for beta4!

@jeremy jeremy merged commit 8ca8a2d into master Apr 24, 2016
jeremy added a commit that referenced this pull request Apr 24, 2016
Refactor handling of :action default in routing
@jeremy jeremy deleted the refactor-handling-of-action-default branch April 24, 2016 22:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants