Search code examples
meteoriron-router

Route using wrong controller?


I have 2 controllers (iron-router), one for access bits (login etc.) and one for the logged in area. But for some reason one of my routes is choosing to use the wrong controller, even though I'm explicitly stating which one to use. Here is the code:

// Controllers
AccessController = RouteController.extend({
  layoutTemplate: 'AccessMaster',
  onBeforeAction: function () {
    if (Meteor.user()) { // If user is logged in then take them to the Dashboard
      this.redirect('/app/dashboard');
    } else {
      this.next();
    }
  }
});
DashboardController = RouteController.extend({
  layoutTemplate: 'DashboardMaster',
  onBeforeAction: function () {
    if (!Meteor.user()) { // If user is not logged in then take them to the login
      this.redirect('/app/login');
    } else {
      this.next();
    }
  }
});

// Routes
Router.route("/app/signup", {
  name: 'Signup',
  controller: 'AccessController'
});
Router.route("/app/login", {
  name: 'Login',
  controller: 'AccessController'
});

Router.route("/app/account", {
  name: 'Account',
  controller: 'DashboardController',
  loadingTemplate: 'Loading',
  action: function () {
    this.render('Account');
  }
});
Router.route("/app/dashboard", {
  name: 'Dashboard',
  controller: 'DashboardController',
  loadingTemplate: 'Loading',
  waitOn: function () {
    …
  },
  action: function () {
    this.render('Dashboard', {
      data: {
        …
      }
    });
  }
});

When I visit app/account I'm redirected to app/dashboard, as directed in the AccessController. Why is the app/account route using the wrong controller logic?

Edit: Oddly, if I remove the controller declaration in the offending route (controller: 'DashboardController') then the template loads fine. So it only uses the wrong controller when I ask it to us a controller.

I must be missing something but that's awfully odd.


Solution

  • I think that your problem comes from the fact that you are using Meteor.user() in both controllers, which is the actual user document. And like any other collection it may not be immediately ready when the application starts.

    If you add a console.log(Meteor.user()) in your controllers, you will see that it is first briefly undefined before returning the user document. So the route is using the right controller but Meteor.user() is undefined so you are redirected to /app/login where Meteor.user() (probably ready now) returns the documents so you get redirected to /app/dashboard.

    To prevent such behavior I use Meteor.userId() which is always available no matter what. And I only use Meteor.user() when I have first tested that Meteor.userId() returned something and if I need more information about the user.