如何正确设置RoR通道来回发送数据

问题描述 投票:2回答:1

[我试图在ActionCable的帮助下模拟语法拼写检查,但是我有点挣扎着去理解如何

  • 设置身份验证
  • 来回广播数据

我阅读了很多文章,包括官方文档,但我感到困惑。所以,我要做的第一件事是在config/application.rb中添加以下内容:

    # Mount ActionCable.
    config.action_cable.mount_path = '/websocket'

我还设置了身份验证:

module ApplicationCable
  class Connection < ActionCable::Connection::Base
    identified_by :current_user

    def connect
      self.current_user = find_verified_user
    end

    private

    def find_verified_user
      current_user = User.find_by_api_key(token)
      if current_user
        current_user
      else
        reject_unauthorized_connection
      end
    end

    def token
      # TODO: verify if this is really safe.
      request.headers[:AUTHORIZATION].split('=').last
    end
  end
end

我不使用device,并且我的身份验证基于令牌。每个用户都有一个固定的API令牌,就是这样。

希望认证是正确的,如果这是不正确的话,如果有经验的人可以指出我,我将不胜感激。

现在,我创建了一个名为spell_checking_channel的频道:

class SpellCheckingChannel < ApplicationCable::Channel
  def subscribed
    stream_from 'spell_checking_channel_' << current_user.id
  end

  def unsubscribed
    # Any cleanup needed when channel is unsubscribed
  end
end

一旦从前端接收到数据,我想调用SpellChecker.call('text')并将结果广播回去。我知道,我在此方面寻求帮助是荒谬的,但我确实没有找到任何示例。另外,我应该对unsubscribed方法执行任何操作吗?

ruby-on-rails actioncable
1个回答
1
投票
ActionCable是WebSockets的包装,在websocket连接浏览器上,它传递的cookie与常规请求一样,这就是为什么devise和类似基于cookie的auth方法起作用的原因。对于基于令牌的身份验证,更容易在参数中传递令牌,如下所示:

const my_token = '...'; const cable = ActionCable.createConsumer(`/websocket?token=${my_token}`);

它将在连接的request.params[:token]中。

在您的js中将数据发送到频道:

const channel = cable.subscriptions.create({ channel: "SpellCheckingChannel" }, { received(data) { // handle data from channel in some way console.log("received from rails:", data); } }); channel.send({ some_data_to_rails: "goes_here" })

在后端:

class SpellCheckingChannel < ApplicationCable::Channel def subscribed # here we instruct ActionCable to send messages from following topic stream_from "spell_checking_channel_#{current_user.id}" # there may be multiple subscriptions in one channel: stream_from "spell_checking_channel_common" end def receive(data) # channel.send(data) ends up here ActionCable.server.broadcast("spell_checking_channel_#{current_user.id}", { this_goes_back: "to js" }) if data[:foo] == "bar" ActionCable.server.broadcast("spell_checking_channel_common", { hey_listen_all: "lala" }) end end end

主要技巧是,您可以在应用程序中的任何地方使用ActionCable.server.broadcast,不仅可以在通道中使用-例如,在通道中,您可以排队后台作业,然后将其结果发送到通道中
© www.soinside.com 2019 - 2024. All rights reserved.