【问题标题】:Rails - How to check for online users?Rails - 如何检查在线用户?
【发布时间】:2012-05-29 19:31:30
【问题描述】:

检查页面上当前在线用户数量的最佳方法是什么?

【问题讨论】:

    标签: ruby-on-rails ruby


    【解决方案1】:

    保存在 Redis 中

    Yuri Barbashow 的 answer 但使用 Redis (nice introdution for Rails):

    # config/initializers/redis.rb
    
    $redis_onlines = Redis.new
    # it's the simplest way, but i'd recommend:
    # $redis_onlines = Redis.new path: "/tmp/redis.sock", db: 15, driver: :hiredis
    # => hiredis driver more fast
    # => use unix domain socket if it's possible
    # => default db is No.0, but it is better to use a specific database
    #    and No.0 leave for testing-development-and-more-and-more
    

    宝石文件

    # Gemfile
    
    gem 'redis'
    gem 'hiredis' # optional
    # don't forget to run `bundle`
    

    设置为online

    # app/controllers/application_controller.rb
    after_filter :set_online
    # the Rails 4 way is:
    # after_action :set_online
    
    private
    
      # set to online
      def set_online
        if !!current_user
          # using separate Redis database
          # such as $redis_onlines = Redis.new db: 15
          # value not need, only key
          $redis_onlines.set( current_user.id, nil, ex: 10*60 )
          # 'ex: 10*60' - set time to live - 10 minutes
        end
      end
    

    在线吗?

    # app/models/user.rb
    
    def online?
      $redis_onlines.exists( self.id )
    end
    

    还有小红利(如果你使用单独的 redis 数据库)

    # app/cpntrollers/application_controller.rb
    
    def all_who_are_in_touch
      $redis_onlines.keys
      # => [ "123", "234", "1", "23" ]
      # array of ids
    end
    

    #UDP1 匿名返工

    设置为online

    # app/controllers/application_controller.rb
    
      def set_online
        if !!current_user
          $redis_onlines.set( "user:#{current_user.id}", nil, ex: 10*60 )
        else
          $redis_onlines.set( "ip:#{request.remote_ip}", nil, ex: 10*60 )
        end
      end
    

    在线吗?

    # app/models/user.rb
    
    def online?
      $redis_onlines.exists( "user:#{self.id}" )
    end
    

    所有联系的人:

    # app/cpntrollers/application_controller.rb
    
    def all_signed_in_in_touch
      ids = []
      $redis_onlines.scan_each( match: 'user*' ){|u| ids << u.gsub("user:", "") }
      ids
    end
    
    def all_anonymous_in_touch
      $redis_onlines.scan_each( match: 'ip*' ).to_a.size
    end
    
    def all_who_are_in_touch
      $redis_onlines.dbsize
    end
    

    #UDP2 建议

    1. 使用before_filter 而不是after_filter
    # app/controllers/application_controller.rb
      before_filter :set_online # before_action for Rails 4
    
    1. 如果您观看匿名(例如session[:user_id] 是当前用户的 id)
    # app/controllers/session_controller.rb
      before_filter :clear_from_signed_in_touch, only: :destroy
      before_filter :clear_from_anonymous_in_touch, only: :create
    
      private
    
        def clear_from_anonymous_in_touch
          $redis_onlines.del( "ip:#{request.remote_ip}" )
        end
    
        def clear_from_signed_in_touch
          $redis_onlines.del( "user:#{session[:user_id]}" )
        end
    

    后记:Redis | set | exists | expire | scan | scan_each | redis-rb | hiredis | nice introduction for beginners

    【讨论】:

      【解决方案2】:

      最简单的方法是将 last_online 时间戳添加到您的用户模型中,然后为名为 online_now 的用户定义一个范围

      class User < ActiveRecord::Base
        def self.online_now
          where("last_online > ?", 15.minutes.ago)
        end
      end
      

      【讨论】:

      • 你如何填写“last_online”字段?
      猜你喜欢
      • 1970-01-01
      • 2020-02-07
      • 2016-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-30
      • 2017-05-28
      • 2014-12-28
      相关资源
      最近更新 更多