Решение
Добавление этого кода в конец моего API-метода решило проблему:
MessageBus.publish("/topic/#{@topic.id}", reload_topic: true, refresh_stream: true)
Это должно обновить состояние не только для текущего пользователя, но и для любого другого, кто просматривает тему.
Исследование, приведшее к этому решению
Читайте дальше, если хотите проследить за моим анализом кодовой базы. Я делюсь этим для тех, кому это может быть полезно.
Что такое MessageBus?
Согласно объяснению Сэма о MessageBus (2013), похоже, что Ruby-код может публиковать и подписываться, тогда как JavaScript-код может только подписываться. Хорошо, значит, в рамках этой предлагаемой архитектуры мой серверный код будет отвечать за уведомление интерфейса.
Есть ли пример использования 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)
Это было финальное решение, которое я выбрал.
Что происходит, когда браузер получает обновление?
Контроллер тем подписан на обновления темы, которую он в данный момент просматривает. Он запускает событие “post-stream:refresh”, которое инициирует обновление. Единственное, что я могу найти слушающим на другом конце, — это ScrollingPostStream, который привязывает метод _refresh к событию. Похоже, именно он фактически выполняет обновление.
Из этого я делаю вывод, что если бы я хотел обновить только текущего клиента, не отправляя обновление другим, я мог бы вызвать тот же код самостоятельно:
this.appEvents.trigger("post-stream:refresh", args)
И похоже, что это можно вызвать из любого компонента.
А как насчет оригинальной реализации move_posts? Публикует ли она в MessageBus?
При изучении ядра я вижу: метод контроллера тем move_posts() вызывает move_posts_to_destination(), который вызывает topic.move_posts(), который вызывает new PostMover(), а затем либо to_topic(), либо to_new_topic(). Эти методы не вызывают MessageBus, но они вызывают DiscourseEvent.trigger().
Я вызываю topic.move_posts() из своего пользовательского API-метода. Таким образом, мой код обращается напрямую к модели, минуя любую существующую логику контроллера:
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 обычно не публикуется при перемещении темы.