频道似乎没有被设计为特定于页面(就像控制器不是特定于页面一样),但您可以确定频道的范围(正如您尝试做的那样),以便订阅只接收给定类别的消息.
您可以通过在布局文件的头部放置类似的内容来选择性地将频道的 js 文件包含在页面中:
<%= javascript_include_tag 'channels/'+params[:controller] %>
而不是在您的 cables.js 文件中执行 //= require_tree ./channels。
但这有一个缺点,即要求您在 config\initializers\assets.rb 初始化程序的预编译数组中包含 js 文件并重新启动服务器:
Rails.application.config.assets.precompile += %w( channels/categories.js )
通道定义是您确定流的范围,使用带有模型的 stream_for,这使得连接 ID 是唯一的,例如 categories:Z2lkOi8vcmFpbHMtc3RaaaRlci9Vc2VyLzI 而不仅仅是 categories。
app/channels/ranking_channel.rb
class RankingChannel < ApplicationCable::Channel
def subscribed
category = Category.find(params[:category_id])
stream_for category
end
...
end
您将category_id 从客户端页面发送到服务器。在这里,我们通过 DOM 中 #category 元素上的 data-category-id 属性来实现(使用 jQuery 语法,但可以很容易地转换为直接 js)。
app/assets/javascripts/channels/categories.js
$( function() {
App.categories = App.cable.subscriptions.create(
{
channel: "RankingChannel",
category_id: $("#category").data('category-id')
},{
received: function(data) {
...
}
}
);
});
因此,在您看来,您需要在生成页面时包含类别 ID:
app/views/categories/show.html.erb
<div id="category" data-category-id="<%= @category.id %>">
<div class="title">My Category</div>
...
</div>