2

I've configured all users to be created with an empty favorites array: user.favorites: []

Since the users collection is treated differently, how should I publish, subscribe, and access subscribed favorites data in angular-meteor?

Here's what I have so far:

// Meteor.methods ==========================================
addFavorite: function(attendeeId){

var loggedInUser = Meteor.user();
if( !loggedInUser ){
  throw new Meteor.Error("must be logged in");
}

    loggedInUser.favorites.push(attendeeId);
    loggedInUser.username = loggedInUser.username+"x";

    console.log(loggedInUser.favorites);

}


// controller ========================================
    $scope.addFavorite = function(attendeeId){
        $meteor.call("addFavorite", attendeeId);
    }

// server =======================================================
Meteor.publish('myFavorites', function(){
    if(!this.userId) return null;

    return Meteor.users.find(this.userId);
});

Meteor.users.allow({

    insert: function(userId, doc){
        return true;
    },

    update: function(useId, doc, fieldNames, modifier){
        return true;
    },

    remove: function(userId, doc){
        return true;
    }

});

User.favorites is empty. When addFavorite is called, it logs an array with a single userId that doesn't update the mongoDB at all. It looks as if Meteor.user() isn't reactivly updating. Does anyone know what I'm doing wrong? Thank you!

EDIT Latest iteration of code. Favorites are passed into $scope.favorites but isn't reactive. How do I fix this? Thanks!

// publish
Meteor.publish('myFavorites', function(){
    if(this.userId){
        return Meteor.users.find(this.userId, {
            fields: {
                favorites: 1
            }
        });
    }else{
        this.ready();
    }
});

// subscribe
$meteor.subscribe('myFavorites')
    .then(function(subscriptionHandle)
{
    var user = $meteor.collection(function(){
        return Meteor.users.find({_id: Meteor.userId()});
    });
    $scope.favorites = user[0].favorites;
});
4

1 回答 1

2

tldr;

帐户收集是反应式的,但默认情况下仅发布用户名、电子邮件和个人资料字段。最快的解决方法是将收藏夹作为新字段附加到 User.profile 对象上。

// Meteor.methods ==========================================
addFavorite: function(attendeeId){

var loggedInUser = Meteor.user();
if( !loggedInUser ){
  throw new Meteor.Error("must be logged in");
}
    if (loggedInUser.profile.favorites){
        loggedInUser.profile.favorites.push(attendeeId);
    }
    else {
        loggedInUser.profile.favorites = [];
        loggedInUser.profile.favorites.push(attendeeId);
    }
    loggedInUser.username = loggedInUser.username+"x";

    console.log(loggedInUser.profile.favorites);

}

虽然现在您可能正在写信给用户,您可以使用meteor mongo-->进行验证db.users.find().pretty(),但订阅不会发布您的收藏夹字段。

替代方法

或者,您可以发布收藏夹字段

// Server code --------
Meteor.publish("userData", function () {
  if (this.userId) {
    return Meteor.users.find({_id: this.userId},
                             {fields: {'favorites': 1}});
  } else {
    this.ready();
  }
});

自以为是的 Meteor.users 哲学

我喜欢围绕 3 个属性来构建我的用户对象:

  • User.profile --> 发布到客户端,客户端可以通过客户端代码直接修改
  • User.public --> 发布到客户端,但不可修改,除非通过服务器端Meteor 方法
  • User.private --> 不发布到客户端(即只能在服务器代码上读取),并且只能由服务器代码修改(使用客户端模拟)

只需确保在删除insecureautopublish包时使用Meteor.users.allow()服务器代码中的函数仔细检查集合的安全性

meteor list如果您想验证当前项目中是否正在使用insecure和包,请运行至。autopublish注意:默认情况下,Meteor 会在您首次创建应用程序时安装它们)

// Server code --------
Meteor.publish("userData", function () {
  if (this.userId) {
    return Meteor.users.find({_id: this.userId},
                             {fields: {'public': 1}});
  } else {
    this.ready();
  }
});
于 2015-08-23T19:48:53.443 回答