Deep nested routes


#1

How to design the data and ember application for a url something like this…

http://<something>/projects/<id>/iterations/<id>/stories/<id>/task/<id>
http://<something>/projects/01/iterations/123/stories/5/task/8

When designed in a normal many routes under one resource, is this a right technique?:

Scrums.Router.map(function() {
  this.resource('projects', { path: '/' }, function(){      
    this.route('iterations', { path: '/iterations' }, function(){
      this.route('stories', { path: '/stories' }, function(){
        this.route('tasks', { path: '/tasks' }, function(){
        });
      });
    });
  });
});
  • If yes, How to design the data and load models?
  • Is there a better design approach which can be used? mixins?
  • url should be sharable and should load the right views and controller.

#2

From what I’ve understood so far, the routes does not have to correspond to the hierarchy of the model behind it.

If the view that would show task would show it as a nested secttion under story, iteration and project, that is when you would go for nesting like this. Otherwise, you would handle the relationship only in model layer using hasMany and belongsTo et. al.

Please correct me if my understanding is completely wrong.


#3

This is what I understood from your response.

http://<something>/task/10

would load all the corresponding project,iteration,story related to the task based on the data model attached behind per ember design?


#4

Like I mentioned earlier, I am also trying to understand the concepts behind ember itself, as well as ember-data.

The best way to make it clear is by trying it out. The code doesn’t lie. :smile:

So I have put together a fiddle here.

Used FixtureAdapter to give a relationship of

-- Project
  -- Iterations
    -- Tasks

And the routes are like

    App.Router.map(function () {
      this.resource('projects');
      this.resource('project', {path: '/projects/:project_id'});
      this.resource('iteration', {path: '/iterations/:iteration_id'});
      this.resource('task', {path: '/task/:task_id'});
    });

I thought of avoiding story/stories for the singular/plural noise. But I am stuck in trying to get the mappings in place for the FixtureAdapter. I have a feeling that this would work in DSRestAdapter, but I am not sure.

This is the code that is right now commented out in the fiddle:

        App.FixtureAdapter.map('App.Iteration', {
          project: {key: 'project_id'}
        });
    
        App.FixtureAdapter.map('App.Task', {
          iteration: {key: 'iteration_id'}
        });

And the direct link to the task would be http://jsfiddle.net/FloydPink/zqQdF/show/#/task/2000, but perhaps because of the mappings not in place, the iteration and project are coming as null.

If someone else could chime in and comment on this, that would be great.

Also, this is the revision 11 of ember-data. I was getting DS.attr as undefined when I tried to rake dist the current master (which is revision 12).


#5

Thanks a lot. This was a blocker issue for me to design my app. I will try bringing up something on REST and see if project and iteration data comes up in the task.


#6

Could @pwagenet, @wycats, @eviltrout or someone who knows the nested routes paradigm better, take a look and comment on this, please?


#7

Sorry I didn’t reply because I’m not an expert on nested routes, nor are we using ember-data :slight_smile: The routes in Discourse are quite simple and I’ve never had the need for many levels deep.


#8

@eviltrout Based on your experience. Can you suggest a good way to design my application routes. My application is a project manager.

Model:

  • Project
  • Person belongsTo Project
  • Iteration belongsTo Project
  • Story belongsTo Iteration
  • Task belongsTo Story (contains people associated to Project)

How do I go about designing the route? When inside a particular Task , I should be able to refer(or navigate) back to it’s corresponding story, iteration, project


#9

The design of the routes is connected with the way you want to design your UI. For example, if you need to nest the data in the UI, your routes should be usually nested too (because of outlets usage).

This of course does not mean that you need to drop the segments in the URL if you don’t use nestings, if you want to use the full URL, you could have a route with multiple dynamic segments. Could you share a simple mockup of the application you have in mind? It would be much easier to design a router in such case.


#10

As @drogus said, the biggest reason behind nesting is using outlets. It is actually quite easy to try out different variations since the namespce for a resource is always top level.

In your example it all depends on how you’re presenting the data. If you want to display both the parent and the child at the same time (for example master-detail setup), then you want to use nesting. Otherwise nesting won’t give you any benefits :slight_smile:


#11

@drogus and @darthdeus I agree. This is my design w/ screenshot

This is the wireframe of my application planned. Every navigation will land into the main outlet. Top header contains:

  • Search
  • Profile
  • Login/Logout/Register

Second header is breadcrumb link back to:

  • Story
  • Iteration
  • Project

Main area is my common {{outlet}}. This is the area which will be used to load whichever context the current user is in:

  • When in Project. List of projects and actions to New/delete/edit project
  • When in Iteration. List of Iteration w.r.t the project and actions to New/delete/edit iteration
  • When in Story. List of Story w.r.t the project & iteration and actions to New/delete/edit story
  • When in Task. List of Task w.r.t the project, iteration & story and actions to New/delete/edit Task

There is also comment section for each level.


#12

From the code:

  route: function(name, options) {
    Ember.assert("You must use `this.resource` to nest", typeof options !== 'function');

So far it looks to me like the current design of Ember isn’t really meant for deeply nested resources. Instead it looks like you should go for routes with multiple dynamic parts and then manually setting up the nested relationships!? I think a lot of developers assume (especially those with a Rails background) assume that nested resources “just work”. One could argue that you should usually shouldn’t represent more than 2 levels of resource nesting in a view (one master-detail rel). So this “limit” might be a good thing?


#13

So to clarify, I do have a UI that would be nested. My url matches my nesting.

Is this the best practice for creating nested route?

URL - /#/clients/1/claims/1/lines/1/flags/1

App.Router.map(function () {
  this.resource("client", { path: 'clients/:client_id' }, function () {
    this.resource("claims", function() {
      this.resource('claim', { path: 'clients/:client_id/claims/:claim_id' }, function () {
        this.resource('lines', function () {
          this.resource('line', { path: 'clients/:client_id/claims/:claim_id/lines/:line_id' }, function () {
            this.resource('flags', function () {
              this.resource('flag', { path: 'clients/:client_id/claims/:claim_id/lines/:line_id/flags/:flag_id' });
            });
          });
        });
      });
    });
  });
  
});

Do/Can I shorten the paths in path: because the resource is nested?


#14

Hi, @coderstash. See: http://emberjs.com/guides/routing/defining-your-routes/#toc_nested-resources


#16

I read the guide. But still trying grok nested routes is still very confusing. Does anybody know of a simple JSBin example that shows the deeply nested resources in action? Preferably with some basic fixture data.

I am trying to build a UI similar to the one described in this thread.


#17

This blog post explains nested routes very well.