A Programmer's Dream

Learning Ember in VS Code -- Routing: Optional Dynamic Segments

Posted by Stephen Wrighton on 06 Nov 2018

Or more accurately, making me cry about routing. 

I was working on something that I often use as a test development product when trying new tools and design paradigms.  Basically, it's a story publishing system similar in nature to FictionPress.com or FanFiction.net.  I like this, because it's a fairly complex scenario, but still within the realm of (what I see as) an understandable domain. 

I like this as a problem space because it has complex structures.  At its heart is a STORY, and this story would have attributes (such as title, author, category) and 1 to N CHAPTERS.  While each chapter would have attributes (chapter title, content, etc) would have 0 to N COMMENTS. 

This problem domain gives me nested data elements 3 levels deep, multiple avenues for data filtering and congestion, as well as users at various levels which would impact all of the data elements. 
So, I started working on it in Ember, and was doing fairly well until I hit where I was building the route needed to view a specific story, a chapter at a time.

What I wanted to do here, was to use dynamic segments to control which story and chapter was displayed to the end user. Specifically, the route would be "/r/:story_id/:chapter_id."  Now there are a few things to remember here.  

The first is that while story_id is the actual identifier for the story to be read, chapter_id is not the chapter identifier, rather it would be the ordinal indicator for that chapter as a sequence within the overarching story.  So, a route of /r/123/3 would be the third chapter of story id 123. 

The second is that chapter_id needed to be optional. If I used the route of "/r/123" then I should have automatically been taken to the first chapter of story 123. Likewise any value outside of a number should also take you to the first chapter, while a numeric value larger than the highest ordinal chapter number should take you to the last chapter.   

But most of that is a back end issue. It's the optional dynamic segment of :chapter_id that's we needed to focus on. After all, optional dynamic segments are a concept that just doesn't exist in Ember. 

Worse, is that every example I saw, didn't allow for multiple levels of dynamic segments where the first of them is required and the second of them is dynamic. 

So, I kicked at it, and created routes and configured them in a dozen different ways until I figured out how I could accomplish this. 

What I did was built two routes.   

The first I named "story" and the second I named "story-chapter."   Then, instead of nesting the second option inside the first (which is how most of the examples performed something similar to what I was attempting, I entered two lines into the Router.map function found in router.js. 

This configuration means that I have to routes for the "/r" root route, one which accepts the story_id dynamic segment, and the second which accepts the story_id and chapter_id dynamic segments. 

Then in the story.js file, I used this to navigate from the story route to the story-chapter route. 

Basically, this is the beforeModel function which processes before any data access on the request.  Since we know that without a chapter_id dynamic segment, we're supposed to go to the first chapter, this takes the behavior of forcing you to that place. 

Of course, in story-chapter.js, we can access the various dynamic segments in this fashion: 

Now, I just need to get that commented aspect of things working the way I expect. 

Tweet me @kidananubix if you like this post.