无法显示数据库

时间:2015-08-10 23:31:47

标签: meteor meteor-blaze

我正在与Meteor建立一个论坛,并希望对答案进行评论。答案与单个问题在同一页面上。我能够保存一次提交的评论(我可以查看mongo数据库,我看到我成功提交评论),但我无法使用模板显示它们。我认为问题与出版物和订阅有关,但我无法找到错误。以下是相关的代码片段。

answer_item.js

Template.answerItem.helpers({
  submittedText: function() {
    return this.submitted.toString();
  },
  comments: function() {
    return Comments.find({answerId: this._id});
  }
});

answer_item.html

<template name="answerItem">
...
    <ul class="comments">
      {{#each comments}}
        {{> commentItem}}
      {{/each}}
    </ul>
...
</template>

comment_item.html

<template name="commentItem">
  <li>
    <h4>
      <span class="author">{{author}}</span>
      <span class="date">on {{submitted}}</span>
    </h4>
    <p>{{body}}</p>

  </li>
</template>

comment_item.js

Template.commentItem.helpers({
  submittedText: function() {
    return this.submitted.toString();
  }
});

LIB /集合/ comment.js

Comments = new Mongo.Collection('comments');

Meteor.methods({
  commentInsert: function(commentAttributes) {
    check(this.userId, String);
    check(commentAttributes, {
      answerId: String,
      body: String
    });
    var user = Meteor.user();
    var answer = Answers.findOne(commentAttributes.answerId);

    if (!answer)
      throw new Meteor.Error('invalid-comment', 'You must comment on an answer');

    comment = _.extend(commentAttributes, {
      userId: user._id,
      author: user.username,
      submitted: new Date()
    });

    Answers.update(comment.answerId, {$inc: {commentsCount: 1}});

    comment._id = Comments.insert(comment);

    return comment._id
  }
});

router.js

Router.configure({
  layoutTemplate: 'layout',
  loadingTemplate: 'loading',
  notFoundTemplate: 'notFound',
  waitOn: function() {
    return [Meteor.subscribe('notifications')]
  }
});

QuestionsListController = RouteController.extend({
  template: 'questionsList',
  increment: 5,
  questionsLimit: function() {
    return parseInt(this.params.questionsLimit) || this.increment;
  },
  findOptions: function() {
    return {sort: this.sort, limit: this.questionsLimit()};
  },
  subscriptions: function() {
    this.questionsSub = Meteor.subscribe('questions', this.findOptions());
  },
  questions: function() {
    return Questions.find({}, this.findOptions());
  },
  data: function() {
    var self = this;
    return {
      questions: self.questions(),
      ready: self.questionsSub.ready,
      nextPath: function() {
        if (self.questions().count() === self.questionsLimit())
          return self.nextPath();
      }
    };
  }
});

NewQuestionsController = QuestionsListController.extend({
  sort: {submitted: -1, _id: -1},
  nextPath: function() {
    return Router.routes.newQuestions.path({questionsLimit: this.questionsLimit() + this.increment})
  }
});

FollowedQuestionsController = QuestionsListController.extend({
  sort: {follows: -1, submitted: -1, _id: -1},
  nextPath: function() {
    return Router.routes.followedQuestions.path({questionsLimit: this.questionsLimit() + this.increment})
  }
});

Router.route('/', {
  name: 'home',
  controller: NewQuestionsController
});

Router.route('/new/:questionsLimit?', {name: 'newQuestions'});

Router.route('/followed/:questionsLimit?', {name: 'followedQuestions'});


Router.route('/questions/:_id', {
  name: 'questionPage',
  waitOn: function() {
    return [
      Meteor.subscribe('singleQuestion', this.params._id),
      Meteor.subscribe('answers', this.params._id),
      Meteor.subscribe('comments', this.params._id)
    ];
  },
  data: function() { return Questions.findOne(this.params._id); }
});

Router.route('/questions/:_id/edit', {
  name: 'questionEdit',
  waitOn: function() {
    return Meteor.subscribe('singleQuestion', this.params._id);
  },
  data: function() { return Questions.findOne(this.params._id); }
});

Router.route('/submit', {name: 'questionSubmit'});

var requireLogin = function() {
  if (! Meteor.user()) {
    if (Meteor.loggingIn()) {
      this.render(this.loadingTemplate);
    } else {
      this.render('accessDenied');
    }
  } else {
    this.next();
  }
}

Router.onBeforeAction('dataNotFound', {only: 'questionPage'});
Router.onBeforeAction(requireLogin, {only: 'questionSubmit'});

服务器/ publications.js

Meteor.publish('comments', function(answerId) {
  check(answerId, String);
  return Comments.find({answerId: answerId});
});

1 个答案:

答案 0 :(得分:1)

看起来您需要在评论发布中运行单独的查询,以获取给定问题的所有答案的列表,然后使用该查询的结果获取所有评论的列表答案。

Meteor.publish('comments', function(questionId) {
    check(questionId, String);
    var answerIds = _.pluck(Answers.find({'questionId': questionId}, {fields: {_id: 1}}).fetch(), '_id');
    return Comments.find({answerId: {$in: answerIds});
});

修改

我在我正在处理的应用程序中有类似的功能,遇到了与您遇到的相同问题。我昨天花了几个小时就得出结论,问题与_.pluck语句将Answers游标的结果转换为数组这一事实有关,这会阻止发布函数从被动反应。

在研究了几个解决方案之后,我找到的最好的解决方案是publish composite包。语法有点冗长,但它完成了工作。为了使一切正常工作,您需要将问题,答案和注释的所有发布函数合并到一个发布函数中。在封面下,它会在问题的每个答案上创建observeChanges个观察者,因此它可能是被动的。

Meteor.publishComposite('question', function(questionId) {
    return {
        find: function() {
            return Questions.find({_id: questionId});
        },
        children: [
            {
                find: function(question) {
                    return Answers.find({questionId: question._id});
                },
                children: [
                    {
                        find: function(answer, question) {
                            return Comments.find({answerId: answer._id});
                        }
                    }
                ]
            }
        ]
    }
});