Search code examples
meteoriron-router

Iron-Router checking document existence before route runs


I have a basic chat room App where you can create a room from the main page which calls this method :

createNewRoom: function (){
    //Room containers unique ID for the object
    var room = Rooms.insert({
        createdAt: new Date()
    });
    return room;
},

The rooms are routed like this :

Router.route('/rooms/:_id', {
    name: 'room',
    template: 'chatRoom'
});

I am trying to set it up though so that you can't just type any random ID and get a room, it has to already exist. So I created this iron-router hook:

var checkRoomExists = function() {
    var room = Rooms.findOne({_id : this.params._id});
    if(typeof(room) == "undefined"){
        Router.go('home');
    }
    else {
        this.next();
    }
}

Router.onBeforeAction(checkRoomExists, {
    only : ['room']
});

room in the checkRoomExists always returns undefined though, even if I test the exact same statement elsewhere with the same _id and the room exists. So if I send the link to someone else it will redirect even if the room exists. Is this the wrong type of hook or is there a better way to accomplish this?'

Edit some additional information: This is the code that creates a room the first time around :

Template.home.events({
    'click #create-room' : function(event){
        event.preventDefault();

        Meteor.call('createNewRoom', function(error, result){
            if (error){
                console.log(error);
            }else {
                Session.set("room_id", result);
                Router.go('room', {_id: result});
            }
        });
    }
});

If I try to use the full link after, like http://localhost:3000/rooms/eAAHcfwFutRFWHM56 for example, it doesn't work.


Solution

  • I am trying to avoid users going to some random ID like localhost:3000/rooms/asdasd if a room with that ID doesn't already exist.

    If you want to do this you can follow the next.

    on the Layout configure add this.

    Router.configure({
      layoutTemplate: 'layout',
      loadingTemplate: 'loading',
      notFoundTemplate: 'notFound' //add the notFoundTemplate.
    });
    

    and this simple onBeforeAction.

    Router.onBeforeAction('dataNotFound', {only: 'room'});
    

    Create some sample template like this.

    <template name="notFound">
     <span> Dam this route don't exist <a href="/">go back to home</a>
    </template>
    

    OPTION

    Im not sure if this still working but you can define this on the very last of the routes.js js

    this.route('notFound', {
      path: '*' //this will work like the notFoundTemplate
    });
    

    NOTE

    If you don't have layout template use like this.

    Router.route('/rooms/:_id', {
        name: 'room',
        notFoundTemplate: 'authorNotFound',
        template: 'chatRoom'
    });