Who’s Online

So, how do you tell who’s online? If you’ve been subjected to the abomination that is myspace you’ll have seen that ‘online now!’ indicator. Well, here’s how I solved that one recently.

First up, here’s a list of all the commands you’ll want.

rake create_sessions_table
script/generate model online
script/generate migration add_user_id_to_session_table

move to db-sessions

rake create_sessions_table

First, if you want to make this easier for everyone, move your application over to db-based sessions. It’s relatively painless, and is much faster than file-system. If you’re on memcache, you’re probably beyond this article.

Now edit your config/environment.rb and add/alter this line:

config.action_controller.session_store = :active_record_store

create the model

script/generate model online

Now you’ll need to make a model so we can access all that lovely session data across all sessions.

Edit the model and set the table name to ‘sessions’. while you’re there, create the association for the user

belongs_to :user
set_table_name ‘sessions’

modify the table

script/generate migration add_user_id_to_session_table

The rake task we ran before added a table called sessions with a session_id, data, and updated_at fields. We want to add the user ID to this. In your migration, you want to add a user_id column (change this as necessary for your own setup.)

add_column :sessions, :user_id, :integer

set the user id in your app

now, edit or create a before_filter in your app that sets up the current user, and set the user_id like this:

sess = Online.find_by_session_id(@session.session_id)
sess.update_attribute(:user_id, @session[:user_id])

Of course there are a metric crapton of ways to do this. You could even hook into it from an image-bug in the page and a specialized action somewhere.

now, show me the mon(k)ey!

Now view your online users! This last step, I’ll leave to you, because it can be done in many ways, dependent on database and coding style.

Online.find(:all, :conditions=>[‘updated_at > ?’, Time.now – 5.minutes])

Remember to add indexing to the user_id field, too.

How else do people do this? What about on page cached sites? (I have my own solution, but that’s “a whole `nother article..”)