-
-
Notifications
You must be signed in to change notification settings - Fork 408
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
RFC for router enhancements #154
Conversation
|
||
# Unresolved questions | ||
|
||
- Do optional segments have a default value? |
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.
No, they do not. They're literally skipped in the route parsing pass. The receiving handler should be capable of surviving params.optionalDynamicSegmentValue === undefined
.
6c4bd4d
to
a7dba07
Compare
|
||
# Drawbacks | ||
|
||
It adds some extra complexity to the routes for a feature that we've survived without for years. |
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 complexity has been reduced tremendously by matching segment-at-a-time.
a7dba07
to
0ddd446
Compare
0ddd446
to
1849f2e
Compare
|
||
``` | ||
Router.map(function() { | ||
this.route('product', { path: '(/:region)/:productName' }); |
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 paren would be inside of the segment: /(:region)/:productName
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.
In Rails the parenthesis enclose the slash too.
I don't have a strong opinion on this and if it's technically simpler so be it, but I think that it reads better that way because if you delete everything between parents you don't end up with a double slash.
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.
having (/:region) /
inside also helps if your segment is the last one. In cases when you don't want your URL to be accessible by two different routes, eg. /my-cool-seo-url/
and /my-cool-seo-url
. So you just specify, that additional segment only works, if there is a /
in the end. Also, you might want to have the last segment as empty. And its possible to distinguish when you explicitly say, if there is /
in the end, than segment should appear.
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.
And one more use-case is, that I actually want a lot :)
I have 3 languages -> en
, es
, fr
Default language is en
. I should be able to have access to default route, without language prefix. Eg.
(/:lang)/welcome
Should be translated into:
/welcome
/es/welcome
/fr/welcome
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 think that the example I used is identical.
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.
Yeap, true :)
Hey everybody! This isn't some greenfield proposal–I know exactly how to implement 99% of this and will have it working in an addon you can try in your applications in the next few days (which will also do build-time serialization as a side-effect). @cibernox has been really itching to have these features and wrote this RFC to get the discussion started. |
1e9c40f
to
f331571
Compare
9fcc05d
to
e1da7a7
Compare
@RuslanZavacky @cibernox Y'all's thoughts on parentheses "including the slash" come from the (reasonable!) assumption that Router.map(function() {
this.route('something', { path: '////something////'} );
}); {{#link-to 'something'}}Something{{/link-to}} Output: <a href="/something">Something</a> But, if you move the parentheses outside of the segment definition you've now made it tremendously more difficult to parse. I'm standing firm on this one: the |
@nathanhammond ah, so its not actually required to place it inside. If its easier to parse it, when its outside, I am quite okey with that, @cibernox thoughts? :) |
Regarding constraint I believe that for V1 we should only support regular expressions. Advanced users can still abuse that by throwing in an IIFE that returns a regular expression but we can throw an error at build time (via an AST analysis) to prevent that. Edit: if we can guarantee it's a pure function via AST analysis then I'm okay with it, but in that scenario it should only receive the up-until-that-node parsed |
|
||
All segments can be optional, no matter globs, static or dynamic. | ||
|
||
### Dynamic segments' constraints |
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 can also apply to glob segments.
Edit: Though it can be done, it'll be awkward to implement. Seems unlikely a glob segment will want to be constrained anyway. Let's not support it.
I'm ok with constrain constraints (pun intended) to regexes initially if that simplifies the implementation. Support for functions could be added in the future if people really wants it. I'll remove references to function constrains from the RFC. |
About the parentheses wrapping the slash or not, I didn't suggested because I thought that slashes have a meaning in the routes, but for familiarity with rails. But if the parsing is significantly more complicated that way, let's make it simple. |
d962797
to
d5a9a0a
Compare
@@ -110,15 +113,16 @@ The resolution order stays as it is currently. That is | |||
- Greater number of segments means more specific. | |||
- On the same number of segments, static is more specific than dynamic, and dynamic is more specific | |||
than globs. | |||
- In case of tie, the first defined route wins | |||
- In case of tie in the number and type of segments, the route with more handlers wins. | |||
- If all the previous fail, the first defined route wins | |||
|
|||
Examples: | |||
|
|||
``` | |||
/foo/bar => 'sample1' (two segments, both static) | |||
/foo/dynamic => 'sample2' (two segments, one static, one dynamic) |
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 would be sample4.opt
because it has more handlers.
e56a57c
to
a326284
Compare
a326284
to
ce77794
Compare
@nathanhammond Hi! I just have a small question. Currently I'm using dynamic segments like this:
my router is: this.route (
'xyz',
{
path: ':param/xyz'
}
); But I need param to be optional, so I can have a route |
@IAmJulianAcosta Order inside of the specified path doesn't matter, so this will work just fine. The microsyntax would be |
@nathanhammond Thanks! I want to know also if the addon is ready to use or I'll have to wait a little bit for it. Thanks! |
Great to see this RFC. I have been using optional dynamic segments a lot in Rails, and I think we need one in Ember. Router.map(function() {
this.route('sample', { path: '/foo/(:param)' });
}); Hope this RFC can be merged ASAP. Thanks the great work! |
I have not seen a discussion about default values for optional segments here. Is that not under consideration? Given the one example from the RFC wouldn't it be nice to do something like that: Router.map(function() {
this.route('forecast', {
path: 'forecast/(:scale)',
constraints: { scale: /(celsius|fahrenheit|kelvin)/ },
defaults: { scale: 'celsius' }
});
});
router.serialize('/forecast/celsius'); // => routeName='forecast', params: { scale: 'celsius' }
router.serialize('/forecast/newton'); // => not recognized route.
router.serialize('/forecast'); // => routeName='forecast', params: { scale: 'celsius' } This way the |
@nathanhammond Did you end up making an add-on for this? |
Just came back after needing this... Could we get a message (from core?) what the status is for this? I see a lot of support, no serious objections, is there something which prevents this from going into FCP? |
Ping on the above 😄 |
Router.map(function() { | ||
this.route('forecast', { | ||
path: 'forecast/:scale', | ||
constraints: { scale: /(celsius|fahrenheit|kelvin)/ } |
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 isn't constraints.scale
an array of values?
@simonihmig turning the question around, is there something preventing the community from implementing this via an addon?* *To clarify, what I mean to ask is what's currently preventing people from doing that, is there a lower-level API we can provide that would aid in experimenting? |
@locks tbh, I don't know at all. Regarding low-level APIs it seems @nathanhammond can probably answer this? I understood the purpose of this RFC to get this into core, but when there is a way to implement that as an addon without monkey patching things, I am fine with that. Generally speaking, I would expect these RFCs to enter some defined state after discussion has settled. Like according to https://github.com/emberjs/rfcs#what-the-process-is to be either accepted and merged, or rejected and closed. But this seemed to be kind of left in a limbo, so I just wanted to ask what is preventing this to proceed in whatever way! :) |
Would this also allow us to define routes based on partial segments as well? Specifically, looking to match |
So much effort put into this RFC and now it's dormant... Or what's the status on this? |
Updates for those missing context:
If somebody wants to work on this, I believe the path forward to be:
|
Given the inactivity here I'm going to go ahead and close this. I apologize for the fact that this stagnated and if you would still like to try to move this forward, I'll ensure that it gets a proper review. It's also worth noting that there is some exploratory router work being done as part of Polaris. That may ultimately address these concerns. |
Expand Ember's router with support for optional segments and constraints.
Rendered