订阅Action Cable频道时如何设置参数

Joh*_*ulo 5 ruby-on-rails channel coffeescript ruby-on-rails-5 actioncable

我一直试图让我的头脑绕着动作电缆看似几个月.请帮忙.

我有一个"连接" - 我无法设置,identified_by :current_user因为此端点也需要由使用WebSockets的外部API使用.无法使用浏览器cookie来验证API端点.

文件和支持

连接: /app/channels/application_cable/connection.rb

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

  end
end
Run Code Online (Sandbox Code Playgroud)

渠道: /app/channels/application_cable/channel.rb

module ApplicationCable
  class Channel < ActionCable::Channel::Base
  end
end
Run Code Online (Sandbox Code Playgroud)

我有一个特定的访问频道: /app/channels/visits_channel.rb

class VisitChannel < ApplicationCable::Channel
  def subscribed
    stream_from "visit_#{params[:visit_id]}"
  end
end
Run Code Online (Sandbox Code Playgroud)

然后我有我的coffeescript频道: /app/assets/javascripts/channels/visit.coffee

App.visit = App.cable.subscriptions.create { channel: 'VisitChannel', visit_id: '42' },
  connected: ->
    # Called when the subscription is ready for use on the server

  disconnected: ->
    # Called when the subscription has been terminated by the server

  received: (data) ->
    console.log data

  push: ->
    @perform 'push'
Run Code Online (Sandbox Code Playgroud)

然后我的访问模型回调: /app/models/visit.rb

class Visit < ApplicationRecord

  after_save  :push_to_action_cable

  **** detail of model removed ****

  def push_to_action_cable
    ActionCable.server.broadcast("visit_#{self.id}", self)
  end

end
Run Code Online (Sandbox Code Playgroud)

这是完美的工作,它每次都向控制台提供对象,只有ID为42的对象

这是我的问题:

在coffeescript频道内:发现于/app/assets/javascripts/channels/visit.coffee- 我如何设置,visit_id以便我可以"只听"我想要的访问的变化?

App.visit = App.cable.subscriptions.create { channel: 'VisitChannel', visit_id: 'HOW_DO_I_SET_THIS?' },
  connected: ->
    # Called when the subscription is ready for use on the server

  disconnected: ->
    # Called when the subscription has been terminated by the server

  received: (data) ->
    console.log data

  push: ->
    @perform 'push'
Run Code Online (Sandbox Code Playgroud)

我尝试过的:

我尝试了各种各样的变化:

App.visit = App.cable.subscriptions.create { channel: 'VisitChannel', visit_id: <%= @visit.id %> }
Run Code Online (Sandbox Code Playgroud)

结果是:

ExecJS::RuntimeError in Visits#action_cable
Showing /Users/johnsalzarulo/code/uvohealth/app/views/layouts/application.html.erb where line #9 raised:

SyntaxError: [stdin]:1:81: unexpected <
Run Code Online (Sandbox Code Playgroud)

App.visit = App.cable.subscriptions.create (channel: 'VisitChannel', visit_id: "#{ params[:id] }")
Run Code Online (Sandbox Code Playgroud)

结果是:

ExecJS::RuntimeError in Visits#action_cable
Showing /Users/johnsalzarulo/code/uvohealth/app/views/layouts/application.html.erb where line #9 raised:

SyntaxError: [stdin]:1:93: unexpected :
Run Code Online (Sandbox Code Playgroud)

App.visit = App.cable.subscriptions.create (channel: 'VisitChannel', visit_id: "#{ @visit.id }")
Run Code Online (Sandbox Code Playgroud)

结果是:

visit.self-e04de4513d06884493c48f4065f94d23255be682f915e26766c54bb9d17ef305.js?body=1:4 Uncaught TypeError: Cannot read property 'id' of undefined
    at visit.self-e04de4513d06884493c48f4065f94d23255be682f915e26766c54bb9d17ef305.js?body=1:4
    at visit.self-e04de4513d06884493c48f4065f94d23255be682f915e26766c54bb9d17ef305.js?body=1:18
(anonymous) @ visit.self-e04de4513d06884493c48f4065f94d23255be682f915e26766c54bb9d17ef305.js?body=1:4
(anonymous) @ visit.self-e04de4513d06884493c48f4065f94d23255be682f915e26766c54bb9d17ef305.js?body=1:18
Run Code Online (Sandbox Code Playgroud)

App.visit = App.cable.subscriptions.create (channel: 'VisitChannel', visit_id: "#{ visit.id }")
Run Code Online (Sandbox Code Playgroud)

结果是:

visit.self-b636f38376edc085c15c2cfc4d524bafc5c5163a8c136b80ba1dda12813fc0b5.js?body=1:4 Uncaught ReferenceError: visit is not defined
    at visit.self-b636f38376edc085c15c2cfc4d524bafc5c5163a8c136b80ba1dda12813fc0b5.js?body=1:4
    at visit.self-b636f38376edc085c15c2cfc4d524bafc5c5163a8c136b80ba1dda12813fc0b5.js?body=1:18
(anonymous) @ visit.self-b636f38376edc085c15c2cfc4d524bafc5c5163a8c136b80ba1dda12813fc0b5.js?body=1:4
(anonymous) @ visit.self-b636f38376edc085c15c2cfc4d524bafc5c5163a8c136b80ba1dda12813fc0b5.js?body=1:18
Run Code Online (Sandbox Code Playgroud)

在结束

我尝试过很多种组合.唯一的作品那种被扔一个<script>到该页面,明确订阅访问视图模板,但我没有得到回调的benifit,再加上我知道这是不是"轨方式".

这是几个小时阅读这些文档并试图使这项工作.任何人都可以了解我在这里缺少的东西吗?

Joh*_*ulo 6

这里有几件事情需要考虑:

  1. 所有脚本加载的顺序。
  2. ruby 变量“实例化”的具体时间,(可以访问它们的位置/时间)。
  3. 意识到可以在愚蠢的 CoffeeScript 中使用普通的 JavaScript。

也就是说 - 这是对我有用的解决方案:

文件和支持

除了下面的内容外,上述问题中使用的所有文件都保持不变。要使其正常工作,您需要参考上面的文件和下面的文件以获得完整的堆栈。

我的应用程序的主要模板:app/views/layouts/application.html.erb注意 head 标签内的行yield(:head_attributes)

<!DOCTYPE html>
<html>
  <head <%= yield(:head_attributes) %> >
    <title>Uvo Health</title>
    <%= action_cable_meta_tag %>
    <%= csrf_meta_tags %>
    <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
    <meta name="viewport" content="width=device-width, initial-scale=1">
  </head>

  <body  <%= yield(:body_attributes) %> >
    <%= render 'layouts/navbar' unless @hide_nav %>
    <%= render 'shared/flash_messages' %>
    <%= yield %>
    <%= yield :page_js %>
  </body>

</html>
Run Code Online (Sandbox Code Playgroud)

我尝试在其中使用 actioncable 的页面的视图。在我的情况下,它是:app/views/visits/action_cable.html.erb- 大多数时候它可能是你的show.html.erbindex.html.erb注意content_for

<%= content_for(:head_attributes) do %>data-visit-id="<%= @visit.id %>"<% end %>

<div class='container'>
  <%= render 'visits/visit_overview' %>
</div>
Run Code Online (Sandbox Code Playgroud)

然后在我的访问频道 /app/assets/javascripts/channels/visit.coffee

App.visit = App.cable.subscriptions.create { channel: 'VisitChannel', visit_id: document.querySelector('head').dataset.visitId },
  connected: ->
    # Called when the subscription is ready for use on the server

  disconnected: ->
    # Called when the subscription has been terminated by the server

  received: (data) ->
    console.log data

  push: ->
    @perform 'push'
Run Code Online (Sandbox Code Playgroud)

发生了什么:

  1. 当页面加载时,视图将 data 属性添加data-visit-id到页面的头部。
  2. 通道visit.coffee从页面头部读取该属性。
  3. 然后visit.coffee可以使用这个变量来订阅相应的频道。

其他解决方案不起作用,因为我试图以错误的“顺序”含义访问事物,在实例化之前加载变量。希望这对其他人有帮助。这个难倒我整整5个小时。