We recently needed to implement tracking which users are online at our site. Matt Beedle posted a good starting guide to how to do this, but I found that there were a possible improvements from his tutorial.
Like Matt, we’re using an ActiveRecord session store to track who’s online when. Unlike Matt, we wanted to keep track of when the user last accessed a page, and what page they accessed. The most SQL-efficient way I could find to do this was to add fields directly to the session model and update those. To add the fields to the model, I just created a migration that added the stuff I wanted to track:
add_column :sessions, :user_id, :integer
add_column :sessions, :last_url_visited, :string
Next, I created a before_filter in our application to update these as the user moved through the site, like so:
session.model.update_attribute(:user_id, session[:user_id])
session.model.update_attribute(:last_url_visited, request.url)
With these properties getting updated, all that remained was to write a query to figure out who’s been moving around the site recently. This ended up being as simple as:
online_sessions = CGI::Session::ActiveRecordStore::Session.find( :all,
:select => "user_id, last_url_visited",
:conditions => [ "updated_at > ? and user_id is not null", Time.now() - 30.minutes ],
:limit => 50 )
And that was about it. The tracking is just one SQL UPDATE a pop, and the session find doesn’t need any fancy joins and such, so it ought to scale pretty well.
Not a good solution since exposing the user_id in the session constitutes a security breach…
Better add fields on the user model…
Hi,
What session store are you using ? With the cookie based store, session is a Session::AbstractStore::SessionHash, and therefore, session.model fails.
Regards,
@Jean-Etienne Durand This only works with ActiveRecordStore.
The link you posted http://matt-beedle.com/2006/12/13/rails-how-to-find-out-who-is-online/ doesn’t exist.I need a method to track number of online users in my rails application.
I am using
config.action_controller.session = {
:session_key => ‘_myapp.com_session’,
:secret => ‘fgdg8sdfds0dsfdf3r3’
}
Why add to the session table? If your goal is to find out who is online and what url they last visited why not just add a last_url field to the user model and update that in your before filter, then do something like
User.find :conditions => [“updated_at > ?”, Time.now – 1.hour]
I should mention that if you do this and you’re doing any clever after_save filters it’s important to optimize them. I was generating a profile header image with Image Magick on each save which was making things rather slow.