Ruby On Rails 7 ActionCable 的使用

环境

  • Rails: 7.0.3

  • Ruby: 3.1.1

一、新建一个 Rails 应用

$ rails new demo --api

二、安装 ActionCable

说是安装,实际上只要把 ActionCable 的 Engine 挂载在路由上即可。当然也可以独立运行一个 ActionCable 的服务,这里就不详细说了,具体参照官方文档

# config/routes.rb

Rails.application.routes.draw do
  
  # 这里挂载 engine
  mount ActionCable.server => '/cable'
end

三、配置 config/cable.rb 文件

ActionCable 在 development 环境下默认使用 async adapter 。这个要求 ActionCable 推送消息时必须和 ActionCable 的服务端在同一个进程里,但是这样就没法在 Rails 自带的 console 里边调试了,所以这里我们把它改成 redis adapter。

# config/cable.yml

development:
  adapter: redis
  url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
test:
  adapter: redis
  url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
production:
  adapter: redis
  url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
  channel_prefix: demo_production

四、Redis 配置

因为上面把 ActionCable 的 adapter 设置成了 redis ,所以相应的要求我们的应用要能够连接 Redis 。这里假设我们已经安装好了 Redis。它运行在本地的 6379 端口上,并且我们已经在 Gemfile 里边启用了连接 Redis 的 gem 。

五、创建一个 Channel

这里举例创建一个新闻(news)的 channel

rails g channel news

上述命令会生成一个文件: app/channels/news_channel.rb

我们打开这个文件,设置一下 channel 的名称

# app/channels/news_channel.rb

class NewsChannel < ApplicationCable::Channel
  def subscribed
  	# stream_from "some_channel"
    stream_from "news_channel"    # <- 这一行是新加的
  end 

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

六、启动服务

如果上面的步骤没有出现问题,那么 ActionCable 的服务就已经配置好了,剩下的只需启动 rails 的服务即可

$ rails s 

七、在谷歌浏览器使用 javascript 连接 ActionCable

这里我们尝试在浏览器中使用 javascript 自带的 sdk 连接 ActionCable 的服务。使用 F12 打开 Chrome 控制台,贴上如下代码

let websocket = new WebSocket('ws://localhost:3000/cable')

// 注意!这里的 channel 使用的是 Channel 的类名,不是之前定义的 channel 名称
let identifier = JSON.stringify({ channel: "NewsChannel" }) 

let data = JSON.stringify({ command: "subscribe", identifier})

// 这里在 open 的时候订阅 channel 
websocket.onopen = function(){
  websocket.send(data)
}

// 这里可以定义一些 websocket 连接关闭的操作
websocket.onclose = function(){
	console.log("disconnected!")
}

// 这里是定义接收到推送的消息时所做的处理
websocket.onmessage = function(e){
	console.log(e.data)
}

顺利的话你会看到如下信息

image.png

八、测试推送消息

保持浏览器的页面不要刷新,不然就要重新连接 websocket 了。打开 Rails 自带的 console :

$ rails console

输入如下命令

# 这里的 channel 参数用的就是我们之前定义好的 channel 名称
ActionCable.server.broadcast("news_channel", {title: "hello world"}.to_json)

一般来说输入完会是这样的
image.png

这时再回到浏览器页面,就会看到有这样的一条消息
image.png

这就说明你成功了!

评论