使用 ActionCable 实时更新 Rails App Wall Feed

发布日期:2026-07-03 21:13:04   来源 : 杭州电子商务研究院    浏览量 :8
杭州电子商务研究院 发布日期:2026-07-03 21:13:04  
8

介绍

Rails 6 包含许多现成的功能,可通过 ActionCable 库轻松为您​​的 Web 应用创建发布/订阅(简称 pub/sub)功能。如今,这种要求对于现代 Web 应用来说很常见。例如,假设您想要实现类似于 Facebook 的墙式信息流,其中当系统中创建新帖子时,这些帖子将出现在信息流中,而无需刷新页面。在本指南中,您将了解如何使用 ActionCable 创建发布/订阅机制,以在墙式信息流中呈现新帖子。

基本概念

让我们首先建立发布/订阅系统的基本概念,以便理解 ActionCable 的不同组件。

渠道

频道是客户端程序可以连接以开始接收消息的任何流或位置。在本指南中,您将创建一个wall_channel。广播到此频道的消息将是系统中保存的新帖子。

广播员

广播器是可以向频道发送消息的任何组件。Rails 中的消息以编程方式表示为哈希对象。

订户

客户端以订阅者的身份连接到频道。连接后,如果广播者通过频道发送消息,订阅者将能够看到该消息。在实现方面,使用加载在页面中的javascript代码订阅频道并提供处理收到的消息的回调函数。

设置

首先创建一个新的 Rails 6 项目。您可以随意命名,但出于本指南的目的,该项目将命名为acdemo

      $ rails new acdemo
    

ActionCable 配置文件

您应该在config/cable.yml上找到ActionCable的配置文件。如果您在开发环境中工作,则使用的默认适配器称为async适配器是 ActionCable 使用的排队机制,用于存储要广播到不同频道的消息。async告诉框架使用内存数据存储,这在某些环境中可能不会立即起作用。建议使用本地运行的 Redis 服务器来处理排队。

这是cable.yml中用于开发的默认配置

      development:
  adapter: async
    

将其更改为以下内容以告诉 ActionCable 使用 Redis:

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

Redis 服务器

如果你尚未运行 Redis 服务器,请根据你选择的平台进行安装:

Mac OS X

确保您已经安装了brew

      $ brew update
$ brew install redis
$ brew services start redis
    

Ubuntu

      $ sudo apt install redis-server
$ sudo service redis-server restart
    

视窗

不幸的是,Redis 不适用于 Windows。不过,你可以通过 WSL2 在 Windows 中安装 Ubuntu。安装说明可在此处找到。

创建频道

要创建名为wall_channel的通道,请发出以下命令:

      $ rails g channel wall
    

该命令将生成以下重要文件:

  • app/channels/wall_channel.rb:代表频道的后端组件。现在,确保在订阅方法中调用stream_from “wall_channel”方法。
  • app/javascript/channels/wall_channel.js:客户端代码包含订阅频道时的不同事件处理程序方法。

惯例是,先前发出的命令中的通道名称是wall,它在 Rails 后端转换为wall_channel ,但在客户端代码上称为WallChannel 。

您的app/channels/wall_channel.rb代码应如下所示:

      class WallChannel < ApplicationCable::Channel
  def subscribed
    stream_from "wall_channel"
  end 

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

在文件app/javascript/channels/wall_channel.js中,您将找到三个函数。当您的客户端代码订阅 WallChannel 时,将触发connect ()函数。现在,您可以通过登录到控制台来验证它确实订阅了该频道。

      connected() {
  console.log("Connected to WallChannel");
}
    

您现在可以暂时保留第二个函数disconnected(),但基本上这就是在终止频道订阅后放置额外客户端代码的地方。

第三个函数received(data)是客户端代码处理广播到频道的传入数据的地方,这些数据由 data参数表示。在本例中,data表示您可以附加到页面界面的新创建的帖子。输入以下代码,它将创建表示帖子的 HTML 元素并将其附加到id 为wall的<div>中。

      received(data) {
  wall = document.getElementById('wall');

  wall.innerHTML +=
    "<h2>" + data.title "</h2>";

  wall.innerHTML +=
    "<p>" + data.content + "</p>";
}
    

您的app/javascript/channels/wall_channel.js应如下所示:

      import consumer from "./consumer"

consumer.subscriptions.create("WallChannel", {
  connected() {
    // Called when the subscription is ready for use on the server
    console.log("Connected to WallChannel");
  },  

  disconnected() {
    // Called when the subscription has been terminated by the server
  },  

  received(data) {
    // Called when there's incoming data on the websocket for this channel
    wall = document.getElementById('wall');

    wall.innerHTML +=
      "<h2>" + data.title "</h2>";

    wall.innerHTML +=
      "<p>" + data.content + "</p>";
  }
});
    

创建根页面

创建一个默认根页面,该页面将在从 WallChannel 接收到创建的帖子时“流式传输”这些帖子

在文件config/routes.rb中,输入以下行:

      root to: "pages#index"
    

使用以下代码创建文件app/views/pages/index.html.erb :

      <h1>Wall Posts</h1>
<div id="wall">
</div>
    

默认情况下,Rails 6 已加载由application.js在require('channels')行中调用的所有 JavaScript 通道代码。因此,您的app/javascript/channels/wall_channel.js将在应用程序的所有页面中加载。您可以通过启动 Rails 服务器并刷新根页面来测试这一点。您应该注意到控制台中打印了上一步中编程的Connected to WallChannel。这表明客户端代码(订阅者)现在已连接到WallChannel

创建模型

创建一个名为Post的模型,其属性titlecontent均为字符串类型。

      $ rails g model Post title:string content:string
$ rails db:migrate
    

<

以上内容来自杭州电子商务研究院推送
关注
关于我们
热门推荐
合作伙伴
免责声明:本站部分资讯来源于网络,如有侵权请及时联系客服,我们将尽快处理
Copyright © 2025-2027 ToB产业网址导航 公安备案 浙公网安备33010602013138号 浙ICP备16025413号-9
支持 反馈 关注 数据