興味深いバグが発生した可能性がありますが、この場合、コレクションを監視するときにドキュメントを削除するために使用できる関数がないことが原因である可能性があります。または私は誤用observe
しています...これは非常によくあることです!
これが私が抱えている問題を再現するサンプルコードです。
この記事の執筆時点ではdevelブランチを使用しているので、これが0.3.5で機能するかどうかはわかりません。
observebug.html
<head>
<title>observebug</title>
</head>
<body>
{{> main}}
</body>
<template name="main">
<h1>Example showing possible bug in Meteor wrt observe</h1>
<div>
<p>Try to delete a note. You will notice that it doesn't appear to get deleted. However, on the server, the delete did occur. Refresh the page to see that the delete did in fact occur.</p>
<h2>Notes:</h2>
<ul>
{{#each notes}}
{{> note_row}}
{{/each}}
</ul>
</div>
</template>
<template name="note_row">
<li>{{title}} <button name="delete">delete</button></li>
</template>
observebug.js
// CLIENT
if (Meteor.is_client) {
Notes = new Meteor.Collection("notes_collection");
Meteor.autosubscribe(function () {
Meteor.subscribe("notes_subscription");
});
Template.main.notes = function () {
return Notes.find();
};
Template.note_row.events = {
"click button[name='delete']": function (evt) {
Meteor.call("deleteNote", this._id, function (error, result) {
if (!error) {
console.log("Note deletion successful.");
} else {
console.log("Error when deleting note.");
}
});
}
};
}
// SERVER
if (Meteor.is_server) {
Notes = new Meteor.Collection("notes_collection");
Meteor.methods({
"deleteNote": function (note_id) {
try {
Notes.remove(note_id);
return true;
} catch (e) {
return false;
}
}
});
Meteor.publish("notes_subscription", function () {
var notes = Notes.find({}, {sort: {title: 1}});
var self = this;
// What we're doing here is basically making an exact duplicate
// of the notes collection. A possible use-case for this would be
// to actually make changes to the copied collection on the fly,
// such as adding new fields without affecting the original
// collection.
var upsertHandler = function (note, idx) {
note.some_new_field = 100;
self.set("notes_collection", note._id, note);
self.flush();
};
var handle = notes.observe({
added: upsertHandler,
changed: upsertHandler,
removed: function (note, idx) {
// As far as I can tell, unset won't remove the document,
// only attributes of the document. I don't think there's
// a method to handle actually removing a whole document?
self.unset("notes_collection", note._id);
self.flush();
}
});
self.onStop(function () {
handle.stop();
self.flush();
});
});
// Add example notes
Meteor.startup(function () {
if (Notes.find().count() === 0) {
Notes.insert({title: "Note #1"});
Notes.insert({title: "Note #2"});
Notes.insert({title: "Note #3"});
Notes.insert({title: "Note #4"});
Notes.insert({title: "Note #5"});
Notes.insert({title: "Note #6"});
}
});
}
あなたが見るもの
このアプリケーションを起動すると、6つの「メモ」の例が表示され、それぞれに削除ボタンがあります。を見ることができるように、コンソールを開いておくことをお勧めしますconsole.log
。メモの削除ボタンをクリックします。メモは削除されますが、これはクライアントに反映されません。
問題はobserve
、コレクションのコピーを作成するためにどのように活用しているかにあると思います(元のコレクションに影響を与えることなく操作できます)。一部の属性だけでなく、ドキュメント全体を削除する関数が必要な気がします(unset
)。