2012-12-28 28 views
7

我想弄清楚如何有条件地发送数据到客户端meteor。我有两种用户类型,根据用户的类型,它们在客户端上的接口(以及它们所需的数据是不同的)。您如何有条件地向Meteor的客户端发送数据?

可以说用户是counselorstudent。每个用户文档都有类似role: 'counselor'role: 'student'

学生有像sessionsRemainingcounselor学生的具体信息,并有辅导员之类的东西pricePerSession

我将如何确保Meteor.user()在客户端上有我需要的信息,并没有额外的?如果我以学生身份登录,Meteor.user()应包含sessionsRemainingcounselor,但如果我以辅导员身份登录,则不应该包含这些内容。我想我可能要搜索的是有条件的出版物和流星术语的订阅。

+0

现在我已经得到了一些答案,我不知道我知道如何挑选最好的,因为他们似乎都在表面上工作。我想我想要最简单,最流行的版本,适用于更复杂的情况(即角色不是互斥等) – Diogenes

+0

在这种情况下,您应该选择@debergalis的答案,因为他是创作者之一流星。没有得到比这更多的流星:) – Rahul

回答

13

使用领域选项来只返回领域你想从Mongo查询。

Meteor.publish("extraUserData", function() { 
    var user = Meteor.users.findOne(this.userId); 
    var fields; 

    if (user && user.role === 'counselor') 
    fields = {pricePerSession: 1}; 
    else if (user && user.role === 'student') 
    fields = {counselor: 1, sessionsRemaining: 1}; 

    // even though we want one object, use `find` to return a *cursor* 
    return Meteor.users.find({_id: this.userId}, {fields: fields}); 
}); 

然后在客户端只需要调用

Meteor.subscribe('extraUserData'); 

订阅可以流星重叠。因此,这种方法的优点在于,向客户端发送额外字段的发布功能与Meteor的幕后发布功能一起工作,后者发送基本字段(如用户的电子邮件地址和配置文件)。在客户端,Meteor.users集合中的文档将成为两组字段的联合。

+2

一个微妙的提示:如果用户的角色可以动态更改,则此发布者不会注意到并更改它发布的字段。如果你需要这样做,你现在必须在'observe'之上手动实现它。希望未来流星将有一些做一个完全被动的发布的方式。 –

+0

另外请注意,因为'Meteor.user()'会在'extraUserData'被标记为就绪时更改,所有Autoruns将重新运行两次:第一次登录用户首次加载时,一次加载'extraUserData'时。为了避免这种情况,请改用'Meteor.userId()':它只会改变一次。 –

+0

另请注意,合并重叠记录集(游标)时,只会比较顶级值。这意味着如果一个订阅包含'{a:{x:'x'}}'而另一个订阅包含'{a:{y:'y'}}'(对于具有相同'_id'的文档) **不**如你所期望的那样得到'{a:{x:'x',y:'y'}}',但是任意一个原稿。查看[这个未解决的问题](https://github.com/meteor/meteor/issues/3764),在[封闭的问题](https://github.com/meteor/meteor/issues/903)中有更好的描述。 – BudgieInWA

3

流星用户默认只发布其基本信息,因此您必须使用Meteor.publish手动将这些字段添加到客户端。幸运的是,Meteor docs on publish有将告诉您如何做到这一点的例子:

// server: publish the rooms collection, minus secret info. 
Meteor.publish("rooms", function() { 
    return Rooms.find({}, {fields: {secretInfo: 0}}); 
}); 

// ... and publish secret info for rooms where the logged-in user 
// is an admin. If the client subscribes to both streams, the records 
// are merged together into the same documents in the Rooms collection. 
Meteor.publish("adminSecretInfo", function() { 
    return Rooms.find({admin: this.userId}, {fields: {secretInfo: 1}}); 
}); 

基本上要发布返回某些信息到客户端,当条件满足,和其他信息的通道时,它不是。然后您在客户端上订阅该频道。

在你的情况,你可能想在服务器是这样的:

Meteor.publish("studentInfo", function() { 
    var user = Meteor.users.findOne(this.userId); 

    if (user && user.type === "student") 
    return Users.find({_id: this.userId}, {fields: {sessionsRemaining: 1, counselor: 1}}); 
    else if (user && user.type === "counselor") 
    return Users.find({_id: this.userId}, {fields: {pricePerSession: 1}}); 
}); 

,然后订阅的客户端上:

Meteor.subscribe("studentInfo"); 
+1

哎呀,我们重叠。但是'Meteor.user'在发布函数中不起作用。在我的答案中查看变体。 – debergalis

+0

我的借口是我写了//上面的伪代码!但你是对的;-) – Rahul

+1

我忘了我可以编辑的东西。固定:) – debergalis

0

因为Meteor.users是像任何其他流星集合的集合,你实际上可以改善其像任何其他流星收集公示内容:

Meteor.publish("users", function() { 
    //this.userId is available to reference the logged in user 
    //inside publish functions 
    var _role = Meteor.users.findOne({_id: this.userId}).role; 
    switch(_role) { 
     case "counselor": 
      return Meteor.users.find({}, {fields: { sessionRemaining: 0, counselor: 0 }}); 
     default: //student 
      return Meteor.users.find({}, {fields: { counselorSpecific: 0 }}); 
    } 
}); 

然后,在你的客户端:

Meteor.subscribe("users"); 

因此,Meteor.user()将根据登录用户的角色相应地自动截断。

这里是一个完整的解决方案:

if (Meteor.isServer) { 
    Meteor.publish("users", function() { 
     //this.userId is available to reference the logged in user 
     //inside publish functions 
     var _role = Meteor.users.findOne({ _id: this.userId }).role; 
     console.log("userid: " + this.userId); 
     console.log("getting role: " + _role); 
     switch (_role) { 
      case "counselor": 
       return Meteor.users.find({}, { fields: { sessionRemaining: 0, counselor: 0 } }); 
      default: //student 
       return Meteor.users.find({}, { fields: { counselorSpecific: 0 } }); 
     } 
    }); 

    Accounts.onCreateUser(function (options, user) { 
     //assign the base role 
     user.role = 'counselor' //change to 'student' for student data 

     //student specific 
     user.sessionRemaining = 100; 
     user.counselor = 'Sam Brown'; 

     //counselor specific 
     user.counselorSpecific = { studentsServed: 100 }; 

     return user; 
    }); 
} 

if (Meteor.isClient) { 
    Meteor.subscribe("users"); 

    Template.userDetails.userDump = function() { 
     if (Meteor.user()) { 
      var _val = "USER ROLE IS " + Meteor.user().role + " | counselorSpecific: " + JSON.stringify(Meteor.user().counselorSpecific) + " | sessionRemaining: " + Meteor.user().sessionRemaining + " | counselor: " + Meteor.user().counselor; 
      return _val; 
     } else { 
      return "NOT LOGGED IN"; 
     } 
    }; 
} 

和HTML:

<body> 
    <div style="padding:10px;"> 
     {{loginButtons}} 
    </div> 

    {{> home}} 
</body> 

<template name="home"> 
    <h1>User Details</h1> 
    {{> userDetails}} 
</template> 

<template name="userDetails"> 
    DUMP: 
    {{userDump}} 
</template> 
相关问题