Core f2f proposal: unspecified this.route() models default to parent resource

App.Router.map(function() {
  this.resource('thing', { path: '/thing/:thing_id' }, function() {
    this.route('edit');
  });
});

If you wanted the Edit route’s model to be the Thing loaded in the Thing route, you have to define a model hook on the Edit route to call this.modelFor('thing'), which is pretty repetitive and cumbersome.

Proposal

For this.route() routes that don’t specify a model hook, the model for that route should default to the parent resource’s model.

This should be totally backwards compatible unless someone is doing something extremely strange.

13 Likes

This is a great idea machty, especially since I find myself doing that quite a bit any ways. Totally for this.

Like @knownasilya I find myself doing this manually all the time, especially for index routes.

:+1:

1 Like

How about something for nested resources?

App.Router.map(function() {
  this.resource('thing', { path: '/thing/:thing_id' }, function() {
    this.resource('comments');
  });
});

The default model hook for ThingCommentsRoute could be something like (grossly simplified):

model: function() {
  parentModel = this.modelFor(this.parentRoute);
  if (parentModel) {
    return parentModel.get(this.routeName);
  }
}

:+1:

I counted 10 model hooks in my app that return this.modelFor('<parent_resource>'). This would get rid of a lot of boilerplate.

I actually thought this was already the default! Good thing I haven’t deleted my child routes yet. All they do is define that very same model hook

I am in favor of this. Have 7 routes in my app that would use this functionality.

When I first started using Ember, I just “assumed” that a route inherited its model from its parent resource because it just made sense. Wishful thinking.

+1. Please implement this.

Hey yall,

Due to overwhelming negativity, we’re not going to be implementing this feature.

Just kidding.

There’s one risky corner case to consider regarding backwards compatibility, but I think we’re probably fine.

Basically, presently, if you have a model-less route and haven’t specified a controller for that route, a default empty Ember.Controller will be generated for you to drive the template. Now, that model-less route will inherit the model from a parent, which means the generated controller might now be an Ember.ObjectController or Ember.ArrayController wrapping the model of a parent object. Now, 99.99% of the time this should be fine, but as @alexspeller pointed out, it’s possible that problems might be caused if you’re generating/writing properties entirely within the template, like

{{input value=foo}}
foo is {{foo}}

If foo didn’t exist on the controller, it would create that property. In the case of a Object/Array controller, it would proxy the read/write of foo through to the underlying model.

I think this is mega rare and probably nothing to worry about, but I’d like to get a sense of what other kinds of gotchas might happen by suddenly having routes/controllers inherit their parent models. Help me brainstorm?

@mmun I think we’d only nail like 20% of the use cases if we went down that route but I wanna keep thinking about it.

I’ve been told that @wycats and @tomdale are not too keen on that idea.

Would love to hear the arguments, since I’m not that familiar with implications in the Ember.js internals. I could see pro and cons either way.

Just thought I’d let the thread know that there’s a PR open for this feature at https://github.com/emberjs/ember.js/pull/4246.

As soon as core decides on the specifics, I’ll update it accordingly.

Good news everyone!

This feature is now in the Canary builds, behind the ember-routing-inherits-parent-model flag. More details at my blog post.

How does this work with a route’s index view? Being new to Ember, I don’t know all the details so maybe I’m doing this wrong in the first place. Basically, I’ve defined a model for the “main” route but am trying to use it within the index template but it’s unavailable. Would this feature fix that issue?

Route:

App.DogsRoute = Ember.Route.extend({
    model: function(){
        return this.store.find('dog');
    }
});

Template:

<script type="text/x-handlebars" data-template-name="dogs/index">
    <ul>{{#each}}
        <li>{{name}}</li>
    {{/each}}</ul>
</script>

@Panman8201 yes this will fix exactly that. Note that it just merged into Canary and will be on Beta tomorrow (or over the weekend); just keep that in mind in case you’re expecting it to work right away.

Great! I was trying to use it in the Canary build (because I’m also using the new queryParams functionality) but it wasn’t seem to be working. I’ll take another, closer look later today to see if everything made it in. Thanks