Проверьте, если пользователь онлайн в режиме реального времени
Я хочу проверить, подключен ли пользователь в данный момент. Это должно быть показано в профиле пользователя.
Я получил это в моем application_controller
after_filter :user_activity
private
def user_activity
current_user.try :touch
end
Я определил это в user-model
def online?
updated_at > 10.minutes.ago
end
Я могу проверить в представлении, если пользователь онлайн: (HAML)
- if @user.online?
Это работает, но всегда требуется перезагрузить страницу, чтобы обновить эту информацию. Как это можно сделать в режиме реального времени? Может быть, с помощью ActionCable?
PS: используя devise
3 ответа
Да, Action Cable может быть использован для этого. Руководство по Rails имеет (половину) пример этого здесь: Обзор Action Cable - 6.1 Пример 1: Внешний вид пользователя
По сути, вы создаете AppearanceChannel
и каждый пользователь подписан на него. Подписка на звонки appear
функция для current_user
который затем может быть передан (например, чтобы показать онлайн-статус другим пользователям), как правило, с помощью фонового задания, такого как BroadcastAppearanceJob
, (Я только начал работать через это сам).
Лучший способ сделать это - использовать вашу клиентскую технологию. Сервер может только знать, был ли пользователь активным, основываясь на его последнем запросе к серверу.
Пользователь может просматривать ваше приложение без отправки запроса на сервер и будет отображаться как не подключенный к сети в зависимости от вашего временного ограничения (даже если они активны).
Рассмотрите возможность использования веб-сокетов для достижения этой цели, будь то JavaScript, Obj-C/Swift или Java.
Я попытался с примером Action Cable, но у меня были некоторые проблемы (.disappear не вызывается, когда я перезагружаю сервер, также трудно обрабатывать, когда пользователь открывает несколько вкладок и т.д....)
Таким образом, простейшим рабочим решением будет способ вызывать сервер каждые 5 минут, например, в javascript:
setInterval(function(){
var xhttp = new XMLHttpRequest();
xhttp.open("GET", "/i_am_still_here", true);
xhttp.send();
}, 5*60*1000);
и так в контроллере
def i_am_still_here
current_user.update(last_seen_at:DateTime.now)
end
и так в User.rb
def is_online?
last_seen_at > 5.minutes.ago
end
Да, как написал Ноа, для этого естественным выбором является клиентская сторона. Клиент может через выбранный интервал инициировать обновление базы данных, указывая, что они присутствуют. Обнаружение присутствия другого пользователя включает проверку того, достаточно ли свежее их обновление.
Загрузка страницы кажется обязательной, но с помощью ajax она не использует много ресурсов. Вы можете (и должны) даже создать специальный макет для целевой страницы ajax без дополнительной нагрузки, такой как css и js.
Я использую этот javascript в представлении (зависимость: jquery):
function update_presence() {
$.ajax({
url: '/presence',
// data: { "my_get_param": "whatever" },
type: 'GET'
})
.done(function(response){
$('div#last-seen').html(response);
})
}
// run it every 30 seconds
setInterval(update_presence, 30000)
Затем определите маршрут, действие и вид, как обычно. В моемpresence
действие в контроллере у меня есть вызов вспомогательной функции:
update_presence(current_user)
Вспомогательная функция - это единственная строка:
def update_presence(user)
user.update_attribute(:last_seen, DateTime.now)
end
В представлении вы можете отобразить результат, который вам может понадобиться. Мой javascript (см. Выше) отображает результат на странице, но это только для тестирования.
<%= current_user.last_seen %>
В модели у меня есть способ проверить наличие:
def is_present?
self.last_seen > 2.minutes.ago
end
Так что любому пользователю вы можете позвонить @user.is_present?
. Но для динамического обновления индикаторов присутствия на веб-странице, я думаю, необходим еще один вызов ajax.