action-cable
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseActionCable Setup
ActionCable 搭建与使用
Overview
概述
ActionCable integrates WebSockets with Rails to enable real-time features. This guide covers the basic setup in this application.
ActionCable 将 WebSockets 与 Rails 集成,以实现实时功能。本指南介绍了在本应用中的基础配置步骤。
Core Components
核心组件
1. Connection (app/channels/application_cable/connection.rb
)
app/channels/application_cable/connection.rb1. 连接(app/channels/application_cable/connection.rb
)
app/channels/application_cable/connection.rbThe connection authenticates and authorizes the WebSocket connection using Devise/Warden.
ruby
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
if verified_user = env['warden'].user
verified_user
else
reject_unauthorized_connection
end
end
end
end该连接使用 Devise/Warden 对 WebSocket 连接进行身份验证和授权。
ruby
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
if verified_user = env['warden'].user
verified_user
else
reject_unauthorized_connection
end
end
end
end2. Channel (app/channels/application_cable/channel.rb
)
app/channels/application_cable/channel.rb2. 频道(app/channels/application_cable/channel.rb
)
app/channels/application_cable/channel.rbBase channel class for all application channels.
ruby
module ApplicationCable
class Channel < ActionCable::Channel::Base
end
end所有应用频道的基础频道类。
ruby
module ApplicationCable
class Channel < ActionCable::Channel::Base
end
end3. JavaScript Setup (app/javascript/initializers/actioncable.js
)
app/javascript/initializers/actioncable.js3. JavaScript 配置(app/javascript/initializers/actioncable.js
)
app/javascript/initializers/actioncable.jsInitialize ActionCable consumer on the client side.
javascript
import * as ActionCable from '@rails/actioncable'
ActionCable.logger.enabled = false在客户端初始化ActionCable消费者。
javascript
import * as ActionCable from '@rails/actioncable'
ActionCable.logger.enabled = falseBroadcasting Updates
广播更新
With Turbo Streams (recommended)
使用Turbo Streams(推荐)
Subscribe to a stream in views:
slim
= turbo_stream_from record
= turbo_stream_from [record, "channel_name"]Broadcast Turbo Stream updates from controllers or background jobs:
ruby
undefined在视图中订阅流:
slim
= turbo_stream_from record
= turbo_stream_from [record, "channel_name"]从控制器或后台任务广播Turbo Stream更新:
ruby
undefinedAppend content to a target
向目标追加内容
Turbo::StreamsChannel.broadcast_append_to(
[record, "channel_name"],
target: "dom_id",
partial: "path/to/partial",
locals: { record: record }
)
Turbo::StreamsChannel.broadcast_append_to(
[record, "channel_name"],
target: "dom_id",
partial: "path/to/partial",
locals: { record: record }
)
Replace content
替换内容
Turbo::StreamsChannel.broadcast_replace_to(
[record, "channel_name"],
target: "dom_id",
partial: "path/to/partial",
locals: { record: record }
)
Turbo::StreamsChannel.broadcast_replace_to(
[record, "channel_name"],
target: "dom_id",
partial: "path/to/partial",
locals: { record: record }
)
Remove element
移除元素
Turbo::StreamsChannel.broadcast_remove_to(
[record, "channel_name"],
target: "dom_id"
)
undefinedTurbo::StreamsChannel.broadcast_remove_to(
[record, "channel_name"],
target: "dom_id"
)
undefinedExample: Organization-scoped notifications
示例:组织级别的通知
View:
slim
= turbo_stream_from current_organization, "timers"
#notificationsController:
ruby
def start_timer
# ... create timer logic ...
Turbo::StreamsChannel.broadcast_append_to(
[current_organization, "timers"],
target: "notifications",
partial: "timers/notification",
locals: { timer: @timer }
)
end视图:
slim
= turbo_stream_from current_organization, "timers"
#notifications控制器:
ruby
def start_timer
# ... 创建计时器逻辑 ...
Turbo::StreamsChannel.broadcast_append_to(
[current_organization, "timers"],
target: "notifications",
partial: "timers/notification",
locals: { timer: @timer }
)
endConfiguration
配置
Cable URL (config/cable.yml
)
config/cable.ymlCable 地址(config/cable.yml
)
config/cable.ymlyaml
development:
adapter: async
test:
adapter: test
production:
adapter: solid_cable
connects_to:
database:
writing: cable
polling_interval: 0.1.seconds
message_retention: 1.dayyaml
development:
adapter: async
test:
adapter: test
production:
adapter: solid_cable
connects_to:
database:
writing: cable
polling_interval: 0.1.seconds
message_retention: 1.dayRoutes (config/routes.rb
)
config/routes.rb路由(config/routes.rb
)
config/routes.rbActionCable is automatically mounted at :
/cableruby
Rails.application.routes.draw do
mount ActionCable.server => '/cable'
endActionCable 会自动挂载到 路径:
/cableruby
Rails.application.routes.draw do
mount ActionCable.server => '/cable'
endDebugging
调试
Enable logging in development:
javascript
// app/javascript/initializers/actioncable.js
ActionCable.logger.enabled = trueCheck connection status:
javascript
const subscription = consumer.subscriptions.create("ExampleChannel", {
connected() {
console.log("Connected to ExampleChannel")
}
})
console.log(subscription)在开发环境中启用日志:
javascript
// app/javascript/initializers/actioncable.js
ActionCable.logger.enabled = true检查连接状态:
javascript
const subscription = consumer.subscriptions.create("ExampleChannel", {
connected() {
console.log("Connected to ExampleChannel")
}
})
console.log(subscription)Security Considerations
安全注意事项
- Always authenticate connections in
ApplicationCable::Connection - Validate params in channel subscriptions
- Use instead of
stream_forwhen possible for automatic scopingstream_from - Never trust client-side data without validation
- Consider rate limiting for channels that accept client messages
- 始终在中对连接进行身份验证
ApplicationCable::Connection - 验证频道订阅中的参数
- 尽可能使用而非
stream_for以实现自动作用域stream_from - 未经验证绝不要信任客户端数据
- 对接受客户端消息的频道考虑设置速率限制