Search code examples
ember.jsember-dataember-router

ember.js dynamic route issue


I have App.User and App.Contact models that are identical and inherit from a a base class:

App.Person = DS.Model.extend({
    firstName: DS.attr('string'),
    surname: DS.attr('string'),   
    email: DS.attr('string'),
    fullName: function(){
        return this.get('firstName') + " " +  this.get('surname');
    }.property('firstName', 'surname'),
});

App.Contact = App.Person.extend({
});

App.User = App.Person.extend({
});

I want to somehow pass these objects to a new route that will allow me to email them automatically. I have a mail object that references the person as a polymorphic relationship:

App.Mail = DS.Model.extend({
    recipients: DS.hasMany('App.Person', {polymorphic: true}),
});

The problem I have is shown in this fiddle here.

For some reason the model is not getting set in the App.MailPersonRoute route and I am mystified as to why.


Solution

  • Because your router has nested routes:

    App.Router.map(function() {
        this.resource('mail', function(){
            this.route('person', {path: 'person/:person_id'}); 
        });
    });
    

    You are creating a {{linkTo}} passing a nested route name as mail.person:

    <script type="text/x-handlebars" data-template-name="index">
      {{#each model}}
        <p>Mail to {{#linkTo mail.person this}}{{fullName}}{{/linkTo}}
      {{/each}}
    </script>
    

    That must also be reflected to your template names (as per conventions), particularly to the template related to that route. Currently you have:

    <script type="text/x-handlebars" data-template-name="mail">
        in mail with {{email}}
    </script>
    

    It should be:

    <script type="text/x-handlebars" data-template-name="mail/person">
        in mail with {{email}}
    </script>
    

    Nested routes carry the name of their parent resources in its key name, while resources don't have a parent resource in their names, even if they are declared under another resource.


    Note: Not required, but maybe you want to change your serialize to something similar or a more elegant implementation of the following:

    serialize: function(model){
        var _personType = 'contact';
        if(model instanceof App.User) {
            _personType = 'user'
        }
        return {
            person_type: _personType,
            person_id: model.get('id')
        };
    }
    

    This change would also require the routes to be defined similar to the following:

    App.Router.map(function() {
        this.resource('mail', function(){
            this.route('person', {path: ':person_type/:person_id'}); 
        });
    });
    

    Implementing it like this would prevent the href of your links to be equal if you have both User and Contact with the same id. In the current state, if you visit one of these links the browser with think that both links were visited. Again, not a requirement or anything.