Как использовать ActionCable как API

Я создал очень простое приложение, используя Rails 5 beta 1 и ActionCable, чтобы показывать, когда пользователи подключаются к сети и позволяют отправлять сообщения друг другу.

Теперь я хотел бы в основном использовать клиентскую часть ActionCable, реализовать ее в контексте другого приложения (которое работает не на Rails 5) и подключить его к первому приложению для отправки и получения данных (например, онлайн-статус пользователей или сообщений).

Чтобы отправить данные из этого второго приложения, я предполагаю, что могу просто выполнить запрос AJAX POST. Вопрос: Как я могу подписаться на второе приложение для открытого подключения первого приложения?

Или даже: как я могу подписаться на соединение ActionCable моего приложения Rails из другого приложения через API?

Моя догадка заключается в том, что я действительно хочу включить этот кофейник как-то в свое второе приложение:

App.appearance = App.cable.subscriptions.create "AppearanceChannel",
  connected: ->
    # Called when the subscription is ready for use on the server

  disconnected: ->
    # Called when the subscription has been terminated by the server

  received: (data) ->
    # ...

Ответ 1

В то время как решение mwalsher было очень полезно для меня, я недавно нашел запрос на перенос в репозитории Rails с официальным решением моего вопроса.

https://github.com/rails/rails/pull/24991

Я предполагаю, что в ближайшем будущем это будет добавлено в основную документацию. Вот ссылка на официальный actioncable пакет npm: https://www.npmjs.com/package/actioncable

Вы можете использовать его аналогично решению mwalsher с любым JS-приложением. Просто установите пакет npm:

npm install actioncable --save

Здесь пример JS из документации:

ActionCable = require('actioncable')

var cable = ActionCable.createConsumer('wss://RAILS-API-PATH.com/cable')

cable.subscriptions.create('AppearanceChannel', {
  // normal channel code goes here...
});

Изменить: Запрос на перенос был сложен некоторое время, и теперь описание является частью официального Readme - еще не в Rails Guides.

Ответ 2

По сути, вам нужно будет включить копию или порт кода JS ActionCable в другое приложение (https://github.com/rails/rails/tree/master/actioncable/app/assets/javascripts).

Обновление: недавно я выпустил пакет npm под названием actioncable-js, который предоставляет прямой порт Ruby on Rails 5 ActionCable CofeeScript для стандартного JS для использования вне Rails: https://github.com/mwalsher/actioncable-js

Поскольку ActionCable - это всего лишь слой поверх WebSockets HTML5, вы также можете использовать необработанный код JS WebSockets (или любую стороннюю библиотеку) для обработки сообщений.

Протокол сообщений ActionCable несколько описан здесь: https://github.com/NullVoxPopuli/action_cable_client#the-action-cable-protocol. Я буду вставлять ниже для удобства:

  • Подключиться к URL-адресу кабеля действия
  • После успешного завершения соединения отправьте сообщение подписки

    • Подписывающее сообщение JSON должно выглядеть следующим образом: {"command":"subscribe","identifier":"{\"channel\":\"MeshRelayChannel\"}"}
    • Вы должны получить следующее сообщение: {"identifier"=>"{\"channel\":\"MeshRelayChannel\"}", "type"=>"confirm_subscription"}
  • После подписки вы можете отправлять сообщения.

    • Убедитесь, что строка действия соответствует имени метода обработки данных на сервере ActionCable.
    • Ваше сообщение JSON должно выглядеть так: {"command":"message","identifier":"{\"channel\":\"MeshRelayChannel\"}","data":"{\"to\":\"user1\",\"message\":\"hello from user2\",\"action\":\"chat\"}"}
    • Полученные сообщения должны выглядеть примерно одинаково
  • Примечание:

    • Каждое сообщение, отправленное на сервер, имеет ключ команды и идентификатора.
    • Значение канала должно соответствовать имени класса канала на сервере ActionCable.
    • identifier и data избыточно jsonified.

Итак, например (в рубине)

payload = {
  command: 'command text',
  identifier: { channel: 'MeshRelayChannel' }.to_json,
  data: { to: 'user', message: 'hi', action: 'chat' }.to_json
}.to_json