Обновление таблицы присутствия с помощью Action Cable - PullRequest
0 голосов
/ 15 января 2019

Для приложения Rails 5.2.2 с Devise Я реализовал пример присутствия https://guides.rubyonrails.org/action_cable_overview.html#example-1-user-appearances со следующими файлами:

приложение / каналы / 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

Приложение / активы / JavaScripts / кабель / подписки / 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, когда пользователь присутствует или нет.

приложение / модели / users.rb

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

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

На странице индекса main#index Я отображаю список всех пользователей с их статусом присутствия:

приложение / контроллеры / main_controller.rb

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

приложение / просмотров / главная / index.html.erb

<h1>Users</h1>

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

приложение / просмотров / главная / _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 при изменении присутствия пользователя.

1 Ответ

0 голосов
/ 19 июля 2019

Мне кажется, что вы на самом деле просто обновляете статус присутствия пользователя в вашей БД, когда клиент подключается или устанавливает себя как удаленного.

Вам также необходимо транслировать эти события на канал, а другим клиентам нужнодля прослушивания событий и манипулирования DOM.

На стороне клиента, в вашем AppearanceChannel вам необходимо реализовать метод received -> (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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...