Modelling a tennismatch. Can I nest child routes under an unsaved parent?


#1

Hi,

I’m trying to model a tennismatch in Ember. I have the datamodel, it looks right, but what about these routes?

Router.map(function() {
  this.route('matches', function() {
    this.route('new', function () {
      this.route('set', { path: 'sets/:set_nr' }, function () {
        this.route('game', { path: 'games/:game_nr' }, function () {
          this.route('point', { path: 'points/:point_nr' })
        });
      });
    });
  });
});

This seems right to me. As I drill down the URLs I see the correct screens. But what should I do when a button takes the user from /matches/new to /matches/new/sets/1/games/1/points/1

Am I hugely overengineering here? It sure smells that way… Should I even try to nest all these routes under an unsaved Match instance? In other words, is /new only ever supposed te be the last part of a URL?

Perhaps I should just have a big fat component at /match/new and never leave that URL until the match is saved.

I think I can get away with this route structure though but I will need to be able to fetch the new Match (let’s assume there can be only new Match instance at a time). But how would I get that instance from the child routes?


#2

This is a good question.

First off, what does your application do?

As I understand a tennis match, it does feel contrived. What does the URL /matches/new/sets/1/games/1/points/1 show? And /matches? It all depends on your domain modelling.

I would not nest anything and leave everything at /matches/new. Is there a specific advantage of being able to navigate to a point, or to a game during the creation of a match? How do you create those models (game, point) by the way? There is no /matches/:id route?

You can nest under new but it seems weird to leave the URL of an unsaved model. It’s way more common to save the model and redirect to something like /matches/1/game/1.


#3

Thanks!

In the mean time I explored both and I think I actually prefer the nested stuff.

The purpose is to log the entire match, point by point, shot by shot even. After every point important stuff happens. The last point of game finishes the game and should create a new game. The last point of the last set should perhaps complete the match, go into tie break mode, or maybe just create a new set. Having a nested URL structure helps me put stuff in the right place, which I think should be the indidual routes dealing with their respective portion on the score. eh… still following? :slight_smile:

I guess I could save straight away, but I like the fact that this way a can build up an entire (match, set or game) and save it only when it’s completed. Saving it point by point will create like 300 requests for just one match. I mean, that’s okay but maybe your mobile phone would be drained by the end of the match, lol.

To answer your questions:

I can save each individual game, set, or point. if that;s easier

The nesting I like:

a) because semantically it makes sense to transition to a new point once the current one is over. Or for instance to transition to a new set once the last game of a set completes. It’ll also play nice with liquid fire.

b) for code organisation. If I just have one route does that take care of all the logic of saving shots, points, games, sets… ?

FYI: here’s how I load the nested point for a new match:

  // Point route
  model(params) {
    let pointNr = parseInt(params.point_nr);
    let game = this.modelFor("matches.new.set.game");
    let point = game.get('points').findBy("nr", pointNr);

    if (point) {
      return point;
    }

    return this.store.createRecord('point', {nr: pointNr, game: game})
  }

#4

Great! There is no one true way, I guess the general guideline is to understand if each concept deserves to be a model – have its own id, and routes to “crud” it (vs be a fragment and/or be manipulated from a parent route/template)


#5

Yes I may change my mind again about this who knows! But I have the pros and cons a bit clearer now, thank you