-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
Phase 3 of public Router Service - adding urlFor #14979
Conversation
Looking good. What is left? More tests? Really excited about this! |
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.
Looking good!
I think we need test cases for the following scenarios:
router.urlFor('something', { selectedItems: ['a', 'b', 'c'] })
(a query param that is an array)router.urlFor('something', { stuff: null })
router.urlFor('something', { stuff: undefined })
router.urlFor('something', { stuff: 'foo' })
wheresomething
route defines a customserializeQueryParam
method- Tests defining a controller for the target, where the controller throws an error in
init
. The idea here is to ensure that we are not forcing controller instances to be created when generating the URL (which is a significant part of the performance issues surrounding{{link-to}}
).
generate() { | ||
let url = this._routerMicrolib.generate(...arguments); | ||
generate(...args) { | ||
let url = this._routerMicrolib.generate(...args); |
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.
Why do we need this change? As you can see here the transpiled output is the same before and after.
Seems fine to make the change, but I was just curious what motivated it...
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 added this while I was fiddling with the params to ensure they were passed through to _routerMicrolib.generate
in the expected format. I realized that this method handles extracting the params correctly already, so this is just a remnant of that. Will revert for sure!
|
||
if (isFeatureEnabled('ember-routing-router-service')) { | ||
moduleFor('Router Service - urlFor', class extends RouterTestCase { | ||
constructor() { |
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.
This constructor
isn't really needed here, can remove..
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 had been doing some custom work in this constructor, but removed it. The constructor was just left in place. Will remove!
@param {String} routeName the name of the route | ||
@param {...Object} models the model(s) or identifier(s) to be used while | ||
transitioning to the route. | ||
@param {Object} [options] optional hash with a queryParams property |
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.
The RFC suggests that the argument signature for urlFor
is routeName, ...models, queryParams
, however this is proposing routeName, ...models, { queryParams }
(destructuring queryParams
off of the last "options" argument). See RFC details here.
Why are we diverging? Did you discover something during implementation that suggests we should have these diverge from the RFC? I'm guessing that its so that we have parity with .transitionTo
and .replaceWith
, but I wanted to confirm...
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.
My interpretation was that we should mimic the signatures of transitionTo
and replaceWith
, as it's preferable to have a consistent API across all public methods. That said, I think what you said here is totally legit, in that the queryParams
object should be the queryParams itself, not an object having a queryParams
property that is the actual queryParams.
I'm going to revisit all of them for consistency, but I know that EmberRouter
expects an object that has a queryParams
property that it unpacks. If we go this route we may want to revisit how EmberRouter
is handling extracting the QPs.
Thoughts?
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.
Yeah, I think it makes sense to use the same interface as .transitionTo
/ .replaceWith
(which both have options with a queryParams
property on them). We can get @ef4 and others to confirm just before landing, but I think it makes sense to stay consistent for now.
If we do decide to change the API, they should all be changed, which is definitely unrelated to this PR...
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.
As per the RFC:
This takes the same arguments as transitionTo
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.
HAHA! Derp. I just was focusing on the code snippet:
urlFor(routeName, ...models, queryParams)
Which is actually incorrect, it should have said:
urlFor(routeName, ...models, { queryParams })
Or:
urlFor(routeName, ...models, options)
(based on the prose just below)
https://github.com/emberjs/rfcs/blob/master/text/0095-router-service.md#new-method-url-generation
This JSBin Demo demonstrates that a bit more work will be needed to satisfy this constraint. Currently, when |
As I was digging into this, I was able to chart a path forward. Please review #14980, which should resolve the specific entanglement I mentioned above... |
@chadhietala more tests, working out specifics of performance characteristics (@rwjblue already found issues with eager instantiation of controllers), etc. |
@rwjblue thanks for all the investigation! I totally appreciate it. The controller.init -> error test case was one that we'd discussed before, and is definitely one I want to add. I'm going to start listing all the test cases in a todo in the description of this PR, so we can ensure we're covering all the permutations. I've reviewed #14980 and dropped a comment on it. |
Since this is one of the places where we need to improve on performance I think it might be useful to use a spy on methods we know we should not enter or entered a well known amount of times. In the long term we need to get Heimdall instrumentation in here, but I think asserting call counts in the tests can give us some confidence. |
@rwjblue added more tests for permutations of calls. What's left? I think you've addressed the expensive calls in URL generation. Is there any other work that needs to happen there? Are there any other checks we can put in place within tests to ensure we don't regress down the non-performant path? |
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.
Additional tests needed:
- generating path via
routerService.urlFor(...stuff...)
then callingrouterService.transitionTo(pathGenerated)
ends up on the same path asurlFor
generated- no dynamic segments (models) or query params
- with dynamic segments (models) no query params
- no dynamic segments (models) with query params
- with dynamic segments (models) and query params
- Still need tests for paths generated for routes including a custom
serializeQueryParam
Good ideas on the tests! Will work on adding those. The last one where we're testing paths generated for routes including a custom |
Yep, sounds good! Also, those |
Thank you @scalvert! |
This PR represents the second phase of the public router service described in this RFC.
It extends the API with:
urlFor
Status: Work in progress
Reviewers: @locks @rwjblue @ef4
Changes:
urlFor
method in public router serviceurlFor
transitionTo
andreplaceWith
that cover URLs as the first parameterHow to test drive this PR:
yarn start
Open up 2 tabs pointing to http://localhost:4200/tests/index.html, one with Enable Opt Features checked, ensure tests pass