【问题标题】:Update presence table with Action Cable使用 Action Cable 更新存在表
【发布时间】:2019-01-15 15:05:08
【问题描述】:

对于带有 Devise 的 Rails 5.2.2 应用程序,我使用以下文件实现了 https://guides.rubyonrails.org/action_cable_overview.html#example-1-user-appearances 的存在示例:

app/channels/appearance_channel.rb

class AppearanceChannel < ApplicationCable::Channel
  def subscribed
    current_user.appear
  end

  def unsubscribed
    current_user.disappear
  end

  def appear(data)
    current_user.appear(on: data['appearing_on'])
  end

  def away
    current_user.away
  end
end

app/assets/javascripts/cable/subscriptions/appearance.coffee

App.cable.subscriptions.create "AppearanceChannel",
  # Called when the subscription is ready for use on the server.
  connected: ->
    @install()
    @appear()

  # Called when the WebSocket connection is closed.
  disconnected: ->
    @uninstall()

  # Called when the subscription is rejected by the server.
  rejected: ->
    @uninstall()

  appear: ->
    # Calls `AppearanceChannel#appear(data)` on the server.
    @perform("appear", appearing_on: $("main").data("appearing-on"))

  away: ->
    # Calls `AppearanceChannel#away` on the server.
    @perform("away")


  buttonSelector = "[data-behavior~=appear_away]"

  install: ->
    $(document).on "turbolinks:load.appearance", =>
      @appear()

    $(document).on "click.appearance", buttonSelector, =>
      @away()
      false

    $(buttonSelector).show()

  uninstall: ->
    $(document).off(".appearance")
    $(buttonSelector).hide()

然后我将以下两种方法添加到我的 users 模型中,以在用户存在或不存在时更新 is_present 属性。

app/models/users.rb

[...]
def appear
  self.update_attributes(is_present: true)
end

def disappear
  self.update_attributes(is_present: false)
end
[...]

在索引页面main#index 上,我显示了所有用户的列表及其存在状态:

app/controllers/main_controller.rb

[...]
def index
  @users = User.order(:last_name)
end
[...]

app/views/main/index.html.erb

<h1>Users</h1>

<%= render partial: "presence_table", locals: {users: @users} %>

app/views/main/_presence_table.html.erb

<div class="presence-table">
  <table class="table table-striped">
    <thead>
      <tr>
        <th><%= User.human_attribute_name("last_name") %></th>
        <th><%= User.human_attribute_name("is_present") %></th>
      </tr>
    </thead>
    <tbody>
      <% users.each do |user| %>
        <tr>
          <td><%= user.last_name %></td>
          <td><%= user.is_present %></td>
        </tr>
      <% end %>
    </tbody>
  </table>
</div>

问题

当用户的存在发生变化时,如何使用 Action Cable 自动更新表格?据我了解,现有部件应该是可能的,但我不知道该怎么做。

我不希望用户必须重新加载main#index 页面来获取最新的状态列表,而是在用户状态发生变化时推送_presence_table.html.erb 的内容。

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-5 actioncable ruby-on-rails-5.2


    【解决方案1】:

    在我看来,当客户端连接或将自己设置为离开时,您实际上只是在更新数据库中的用户存在状态。

    您还需要将这些事件广播到频道,其他客户端需要监听这些事件并操作 DOM。

    在客户端,在您的AppearanceChannel 中,您需要实现received -&gt; (data) 方法。每次服务器向该频道的订阅者发送事件时都会调用它。

    这里是纯JS代码:

    App.presence = App.cable.subscriptions.create("AppearanceChannel", {
      received: (data) => {
        // here you have access to the parameters you send server side, e.g. event and user_id
        let presenceEl = document.getElementById(data.user_id).querySelectorAll("td")[1]
        if (data.event == "disappear") {
          presenceEl.innerHtml = "false"
        } else {
          presenceEl.innerHtml = "true"
        }
      }
    })
    

    在服务器上app/models/users.rb

    def appear
      self.update_attributes(is_present: true)
    
      ActionCable.server.broadcast("appearance_channel", event: "appear", user_id: id)
    end
    
    def disappear
      self.update_attributes(is_present: false)
    
      ActionCable.server.broadcast("appearance_channel", event: "disappear", user_id: id)
    end
    

    【讨论】:

      猜你喜欢
      • 2018-03-10
      • 1970-01-01
      • 1970-01-01
      • 2017-07-10
      • 2018-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-16
      相关资源
      最近更新 更多