Как создать несколько каналов с помощью Actioncable; как передать переменную в документе в каналы и задания javascript и ruby?

Например, в https://www.youtube.com/watch?v=n0WUjGkDFS0 в 10:36 он упоминает возможность создания нескольких каналов, но как на самом деле это сделать?

В соответствии с Rails 5 ActionCable устанавливает поток из параметров URL переменная может быть определен и передан как параметр, например:

  def subscribed
    stream_from "room_channel_#{params[:roomId]}"
  end

Но в файле javascript перед передачей данных сюда, как передать данные со страницы? В следующем примере отображается ошибка, поскольку предположительно кабель определен до загрузки документа.

App.room = App.cable.subscriptions.create { channel: "RoomChannel", roomId: document.getElementById("message_text").getAttribute("data-room")}

Затем, если кто-то успешно получает данные из документа в переменную здесь и передает их методу stream_from, то, наконец, как правильный канал передается в метод выполнения для использования в широковещательном задании?

  def perform(message)
    ActionCable.server.broadcast 'room_channel_???', message: render_message(message) #, roomId: roomId
  end

Спасибо!


person Laser    schedule 22.04.2016    source источник
comment
У меня такая же проблема, ты разобрался?   -  person Graham Slick    schedule 11.05.2016
comment
Извините, не знаю, почему я не видел этого раньше, ответил на аналогичный вопрос здесь, который включает передачу переменных: stackoverflow.com/questions/36926816/   -  person Laser    schedule 15.07.2016


Ответы (2)


Я многому научился, просмотрев пример ActionCable. Меня тоже смутила документация, которая предлагает парсить параметры и запускать стрим сразу по подписке. Хотя это вариант, вы можете предпочесть подход ниже.

Создайте специальный метод, который можно вызывать со стороны клиента (JS), что-то вроде start_listening:

class RoomChannel < ApplicationCable::Channel
  # Called when the consumer has successfully
  # become a subscriber of this channel.
  def subscribed
  end

  def start_listening room_data
    stop_all_streams # optional, you might also keep listening...
    stream_for Room.find(room_data['room_id'])
  end

  def stop_listening
    stop_all_streams
  end
end

С помощью этого кода (и перезапуска сервера) теперь вы можете вызвать следующую строку, когда вы фактически загрузили комнату:

App.roomChannel.perform("start_listening", {room_id: 20});

Теперь вы можете передавать данные для комнаты куда угодно, используя broadcast_to. Например. из действия RoomMessage after_safe:

RoomChannel.broadcast_to(room, room_message)

Это будет транслировать сообщение всем, кто слушает.

Отделяя момент, когда вы начинаете прослушивать поток, от фактического открытия соединения, упрощается настройка нескольких потоков данных (есть одно соединение, которое может иметь много каналов, у которых может быть много потоков) (просто не закрывайте старые потоки при запуске нового ;) ). Время установки соединения также немного сокращается, хотя обычно это происходит за счет наличия открытого соединения, возможно, уже, как только пользователь входит в систему, что-то, что вы можете легко обойти, подписавшись непосредственно перед тем, как начать слушать.

person murb    schedule 05.10.2016

Я придумал 2 решения этой проблемы.

  1. Это немного глупо - вы можете просто проанализировать URL. Вам всегда нужна часть после последнего «/», поэтому благодаря REST это жизнеспособный вариант.
  2. Лучше один - вы можете обернуть весь код своей клиентской подписки в функцию, которая вызывается при загрузке документа. Таким образом, у вас есть все данные со страницы, которые можно использовать для создания новой подписки.

Надеюсь, вы ответите, если найдете более чистое решение.

person Дмитрий Спивако&    schedule 06.03.2017