web-dev-qa-db-ja.com

Rails:ユーザーの「最後に見た」時間を表示する方法は?

current_sign_in_atlast_sign_in_atの日時を保存するデバイスを使用しています。

ただし、ユーザーが1か月前にログインしたが、最後に5分前にページを表示したとしましょう

それを表示する方法はありますか("ユーザーが最後に見たのは5分前")。

24
Hopstream

これはどう:

  1. 移行を作成して、ユーザーに新しいフィールドを追加し、ユーザーが最後に表示された日時を保存します。

    Rails g migration add_last_seen_at_to_users last_seen_at:datetime
    
  2. アプリケーションコントローラーにアクション前のコールバックを追加します。

    before_action :set_last_seen_at, if: proc { user_signed_in? }
    
    private
    def set_last_seen_at
      current_user.update_attribute(:last_seen_at, Time.current)
    end
    

このように、現在のユーザーが実行するすべてのリクエスト(つまり、アクティビティ)で、最後に表示された属性が現在の時刻に更新されます。

ただし、ログインしているユーザーが多い場合、ログインしているユーザーから要求されたすべてのコントローラーアクションの前に実行されるため、アプリのリソースの一部を消費する可能性があることに注意してください。

パフォーマンスが懸念される場合は、次のスロットルメカニズムをステップ2に追加することを検討してください(この例では、15分でスロットルします)。

before_action :set_last_seen_at, if: proc { user_signed_in? && (session[:last_seen_at] == nil || session[:last_seen_at] < 15.minutes.ago) }

private
def set_last_seen_at
  current_user.update_attribute(:last_seen_at, Time.current)
  session[:last_seen_at] = Time.current
end
47
dchacke

前の回答のパフォーマンスを向上させるには:

  • ユーザーはすでにワーデンをロードしており、すべての属性にアクセスできるため、セッションを使用しないでください
  • update_attributeコールバックを実行して更新しますupdated_at属性、およびupdate_columnない
  • パフォーマンスを向上させるには、ActiveJob/Resque/Sidekiqなどのバックグラウンドワーカーを使用することをお勧めします
  • 高いDBロックを防ぐために、usersテーブルに関連付けられた個別のテーブルを作成し、そこにアクセスを書き込む方がよい

更新されたコード:

before_action :set_last_seen_at, if: proc { user_signed_in? && (user.last_seen_at.nil? || user.last_seen_at < 15.minutes.ago) }

private
def set_last_seen_at
  current_user.update_column(:last_seen_at, Time.now)
end

Deviseプラグインは同様の動作を発生させます(最適化なしで最後に見たばかりです): https://github.com/ctide/devise_lastseenable

8