Search code examples
javascriptmeteoruser-accounts

meteor users not synchronize published sub fields of profile


Working on my social app I've found a strange behavior in the collection Meteor.users, this problem does not occur with other Collections using the same methodologies

I would like to have an initial list of users downloading a minimum number of information for everyone and when I open the panel to a specific user I subscribe a different showing more information if the specified user is a friend of mine.

But after subscribe the client collection Meteor.users is not updated!

CLIENT

Meteor.startup(function() {

    Meteor.subscribe('usersByIds', Meteor.user().profile.friends, function() {

        //... make users list panel using minimal fields

    });

    //performed when click on a user
    function userLoadInfo(userId) {

        Meteor.subscribe('userById', userId, function() {

            var userProfile = Meteor.users.findOne(userId).profile;

            //...
            //make template user panel using full or minimal user fields
            //...

            //BUT NOT WORK!

            //HERE Meteor.users.findOne(userId) keep minial user fields!!
            //then if userId is my friend!

        });         
    }
});

SERVER

//return minimal user fields
getUsersByIds = function(usersIds) {

    return Meteor.users.find({_id: {$in: usersIds} },
                            {
                                fields: {
                                    'profile.username':1,
                                    'profile.avatar_url':1
                                }
                            });
};

//return all user fields
getFriendById = function(userId) {

    return Meteor.users.find({_id: userId},
                            {
                                fields: {
                                    'profile.username':1,
                                    'profile.avatar_url':1
                                    //ADDITIONAL FIELDS                         
                                    'profile.online':1,
                                    'profile.favorites':1,
                                    'profile.friends':1
                                }
                            });
};

//Publish all users, with minimal fields
Meteor.publish('usersByIds', function(userId) {

    if(!this.userId) return null;

    return getUsersByIds( [userId] );
});

//Publish user, IF IS FRIEND full fields
Meteor.publish('userById', function(userId) {

    if(!this.userId) return null;

    var userCur = getFriendById(userId),
        userProfile = userCur.fetch()[0].profile;

    if(userProfile.friends.indexOf(this.userId) != -1)  //I'm in his friends list
    {
        console.log('userdById IS FRIEND');
        return userCur;     //all fields
    }
    else
        return getUsersByIds( [userId] );   //minimal fields
});

Solution

  • This is a limitation or bug in DDP. See this.

    A workaround is to move data out of users.profile.

    Like this:

    //limited publish
    Meteor.publish( 'basicData', function( reqId ){
      if ( this.userId ) {      
    
        return Meteor.users.find({_id: reqId },{
          fields: { 'profile.username':1,'profile.avatar_url':1}
        });
      } 
      else {
        this.ready();
      }
    });
    
    //friend Publish
    Meteor.publish( 'friendData', function( reqId ){
      if ( this.userId ) {
    
        return Meteor.users.find( {_id: reqId, 'friendProfile.friends': this.userId }, {
          fields: {
            'friendProfile.online':1, 
            'friendProfile.favorites':1,
            'friendProfile.friends':1
          }
        });
      } 
      else {
        this.ready();
      }
    });
    
    //example user
    var someUser = {
       _id: "abcd",
       profile: {
         username: "abcd",
         avatar_url: "http://pic.jpg"
       },
       friendProfile: {
         friends: ['bcde', 'cdef' ],
         online: true,
         favorites: ['stuff', 'otherStuff' ]
       }
    }