解决方案
将此添加到我的 API 方法的末尾解决了问题:
MessageBus.publish("/topic/#{@topic.id}", reload_topic: true, refresh_stream: true)
这应该不仅会刷新当前用户,还会刷新查看该主题的任何其他用户。
导致我找到解决方案的探索过程
如果您想跟随我一起浏览代码库,请继续阅读。我分享这些是为了让任何可能需要的人受益。
什么是 MessageBus?
根据 Sam 在 2013 年对 MessageBus 的解释,似乎 Ruby 代码可以发布和订阅,而 Javascript 代码只能订阅。好的,那么在这种提议的架构下,我的服务器端代码将负责通知 UI。
有没有对我有用的 MessageBus 示例?
没有一个插件示例会处理 MessageBus。
GroupArchivedMessage.move_to_inbox! 调用了这段代码,这与我想要的功能有些接近,但这里使用的类型代码对我不起作用。
MessageBus.publish("/topic/#{topic_id}", { type: "move_to_inbox" }, group_ids: [group_id])
这段代码看起来很有希望。
MessageBus.publish("/topic/#{@topic.id}", reload_topic: true, refresh_stream: true)
这是我最终选择的解决方案。
浏览器收到更新时会发生什么?
Topics 控制器(Topics controller)订阅了它当前正在查看的主题的更新。它触发了 “post-stream:refresh”,这会启动刷新。我能找到的唯一在另一端监听的是 ScrollingPostStream,它将一个 _refresh 方法 绑定到该事件。这似乎是实际执行更新的部分。
由此我推断,如果我想只更新当前客户端而不将更新推送到任何其他人,我可以自己调用相同的代码:
this.appEvents.trigger("post-stream:refresh", args)
而且看起来我可以从任何组件调用它。
原始的 move_posts 实现呢?它是否发布到 MessageBus?
调查核心代码,我看到:topic 控制器 move_posts() 方法调用 move_posts_to_destination(),后者调用 topic.move_posts(),然后调用 new PostMover(),接着调用 to_topic() 或 to_new_topic()。这些方法不调用 MessageBus,但它们会调用 DiscourseEvent.trigger()。
我从我的自定义 API 方法中调用 topic.move_posts()。所以我的代码直接调用模型,跳过了任何现有的控制器逻辑:
new_topic = topic.move_posts(current_user, [post.id], {title: title, category_id: category_id})
在我的例子中,move_posts_to() 在序列的最后一步被调用,它调用了以下代码:
DiscourseEvent.trigger(
:posts_moved,
destination_topic_id: destination_topic.id,
original_topic_id: original_topic.id,
)
DiscourseEvent 似乎与 MessageBus 没有关系,但是。也许它只用于服务器内部的生命周期?
所以我得出结论,对于主题移动,通常不会发布到 MessageBus。