Meteor - 在列表对象中呈现所有者的名称 [英] Meteor - rendering the name of the owner in a list objects

查看:89
本文介绍了Meteor - 在列表对象中呈现所有者的名称的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我尝试查找对象的所有者时,我找到了一个找不到对象的错误
我正在尝试渲染。我正在浏览一组视频片段,可以由用户更新或管理。我登录时代码工作正常,但是当我尝试使用它并且我已经注销时,我得到排队任务中的​​异常:TypeError:无法在Object.Template.video_info中读取未定义的属性'_id'。 creatorName

I'm getting an object not found error when I try and lookup the owner of the objects i'm trying to render. I'm looping through a collection of video clips, that can be updated or administered by users. The code works fine when I'm logged in, but when I try to use this and I'm logged out, I get "Exception in queued task: TypeError: Cannot read property '_id' of undefined at Object.Template.video_info.creatorName "

我试图通过这样做来调试:

I've tried to debug this by doing this:

console.log(this.owner);
var owner = Meteor.users.findOne(this.owner);
console.log(owner);

当我检查控制台日志时,我可以看到正在找到正确的用户ID,当我用这个id手动运行Meteor.users.findOne我得到一个返回的用户对象。有没有什么奇怪的关于Meteor中的时间阻止了这个?

When I check the console log, I can see that the correct userid is being found, and when i manually run Meteor.users.findOne with this id I get a user object returned. Is there something strange about the timings in Meteor that is preventing this?

更新:如果我向模板creatorname函数添加try ... catch,那么会记录2个错误但模板仍然呈现...... ???似乎这个模板被调用了两次,一次是在它没有准备好的情况下,再次调用它。为什么会这样。

UPDATE: If I add a try...catch to the template creatorname function then 2 errors get logged but the template still renders... ??? Seems like this template is being called twice, one when it's not ready, and again once it is. Why would that be.

try ... catch块的示例:

Example of the try...catch block:

  Template.video_info.creatorName = function () {
      try{
        var owner = Meteor.users.findOne(this.owner);
        if (owner._id === Meteor.userId())
          return "me";
        return displayName(owner);
      } catch (e){
        console.log(e);
      }
  };

此点以下的原始破产代码

ORIGINAL BROKEN CODE BELOW THIS POINT

这是我的HTML:

<body>
  <div>
    {{> video_list}}
  </div>
</body>
<template name="video_list">
  <h1>Video List</h1>
  {{#each videos}}
    <ul>
      {{> video_info}}
    </ul>
  {{else}}
    No videos yet.
  {{/each}}
  <div class="footer">
    <button>Like!</button>
  </div>
</template>

<template name="video_info">
  <li class="video-list {{maybe_selected}}">
    <img src="{{image}}" />
    <div>
      <h3>{{title}}</h3>
      <p>{{description}}</p>
      <h4>{{creatorName}}</h4>
    </div>
  </li>
</template>

这是在我的client.js

This is in my client.js

Meteor.subscribe("videos");

if (Meteor.isClient) {

  Template.video_list.videos = function() {
    return Videos.find({}, {sort: {title: 1}});
  };

  Template.video_list.events = {
    'click button': function(){
      Videos.update(Session.get('session_video'),{$inc: {likes: 1}});
    }
  }

  Template.video_info.maybe_selected = function() {
    return Session.equals('session_video', this._id) ? "selected" : "";
  }

  Template.video_info.events = {
    'click': function(){
      Session.set('session_video', this._id);
    }
  }

  Template.video_info.creatorName = function () {
    var owner = Meteor.users.findOne(this.owner);
    if (owner._id === Meteor.userId())
      return "me";
    return displayName(owner);
  };
}

if (Meteor.isServer) {
  Meteor.startup(function () {
    // code to run on server at startup
  });
}

这是我的model.js

This is in my model.js

Videos = new Meteor.Collection("videos");

Videos.allow({
  insert: function (userId, video) {
    return false; // no cowboy inserts -- use createParty method
  },
  update: function (userId, video, fields, modifier) {
    if (userId !== video.owner)
      return false; // not the owner

    var allowed = ["title", "description", "videoid", "image", "start"];
    if (_.difference(fields, allowed).length)
      return false; // tried to write to forbidden field

    // A good improvement would be to validate the type of the new
    // value of the field (and if a string, the length.) In the
    // future Meteor will have a schema system to makes that easier.
    return true;
  },
  remove: function (userId, video) {
    // You can only remove parties that you created and nobody is going to.
    return video.owner === userId; //&& attending(video) === 0;
  }
});

var NonEmptyString = Match.Where(function (x) {
  check(x, String);
  return x.length !== 0;
});

var NonEmptyNumber = Match.Where(function (x) {
  check(x, Number);
  return x.length !== 0;
});

createVideo = function (options) {
  var id = Random.id();
  Meteor.call('createVideo', _.extend({ _id: id }, options));
  return id;
};

Meteor.methods({
  // options should include: title, description, x, y, public
  createVideo: function (options) {
    check(options, {
      title: NonEmptyString,
      description: NonEmptyString,
      videoid: NonEmptyString,
      image:NonEmptyString,
      start: NonEmptyNumber,
      _id: Match.Optional(NonEmptyString)
    });

    if (options.title.length > 100)
      throw new Meteor.Error(413, "Title too long");
    if (options.description.length > 1000)
      throw new Meteor.Error(413, "Description too long");
    if (! this.userId)
      throw new Meteor.Error(403, "You must be logged in");

    var id = options._id || Random.id();
    Videos.insert({
      _id: id,
      owner: this.userId,
      videoid: options.videoid,
      image: options.image,
      start: options.start,
      title: options.title,
      description: options.description,
      public: !! options.public,
      invited: [],
      rsvps: []
    });
    return id;
  },

});

///////////////////////////////////////////////////////////////////////////////
// Users

displayName = function (user) {
  if (user.profile && user.profile.name)
    return user.profile.name;
  return user.emails[0].address;
};

var contactEmail = function (user) {
  if (user.emails && user.emails.length)
    return user.emails[0].address;
  if (user.services && user.services.facebook && user.services.facebook.email)
    return user.services.facebook.email;
  return null;
};


推荐答案

我想我找到了这个解决方案。在阅读了Meteor中的缓存工作后,我发现了订阅模型及其与流星的关系,以及 http:/ /docs.meteor.com/#dataandsecurity 。之所以成功失败的原因是,在第一次加载时,数据仍然被缓存在最小值中。我正在检查帐户登录服务已配置以检查用户数据是否已加载。我目前正在使用这个,因为我找不到订阅Metor用户服务的方法,但我的猜测是帐户登录服务将依赖于Metor用户集合。我目前的解决方案如下所示:

I think I've found the solution to this one. After reading about the caching works in Meteor, I've discovered the subscription model and how this relates to meteors minimongo http://docs.meteor.com/#dataandsecurity. The reason this was failing then succeeding was that on the first load the data is still being cached in minimongo. I'm currently checking against Accounts login Services Configured to check if the user data has been loaded. I'm currently using this because I can't find a way to subscribe to the Metor users service, but my guess is that the Accounts login service would rely on the Metor users collection. My current solution looks like this:

if(Accounts.loginServicesConfigured()){
  var owner = Meteor.users.findOne(this.owner);
  if (owner._id === Meteor.userId())
    return "me";
  return displayName(owner);
}

目前这似乎工作正常。我还在深入研究如何订阅这个用户服务。我在搜索此解决方案时发现了许多真正有用的参考资料

Currently this appears to be working correctly. I'm still delving into how to subscribe to this users service.Couple of really userful resferences I found while searching for a solution for this

  • https://github.com/oortcloud/unofficial-meteor-faq
  • http://psychopyko.com/cool-stuff/meteor-6-simple-tips/
  • https://groups.google.com/forum/#!topic/meteor-talk/QKXe7qfBfqg

这篇关于Meteor - 在列表对象中呈现所有者的名称的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆