Rails - How to find out who is online
Well, this is my first post. I was frustrated in to starting this blog, through searching the internet for solutions to various programming problems, and finding either nothing, or only half the answer. Hopefully I will be able to help others solve some of their problems faster. Recently I have been writing a dating site in ruby on rails. One quite important feature of this site is a list of members who are currently online. After a couple of days of pain, here’s the pretty simple solution to the problem:
First off this only works if you use ActiveRecord to manage your sessions. To do this you must uncomment the following line in your environment.rb file:
config.action_controller.session_store = :active_record_store
Then create the sessions table by running the following command from your RAILS_ROOT:
rake db:sessions:create
Now, whenever a user logs in to your application add their id to the session. In my app at the moment it looks something like this:
member = Member.new( @params[ :member ] )
member = Member.find( :all, :conditions => "screen_name = '#{member.screen_name}' AND password = '#{member.password}'" )
if member != nil
session[ :member_id ] = member.id
redirect_to :action => 'success'
else
redirect_to :action => 'form'
end
This code will need work for a production environment, for one thing it is open to SQL injection attacks.
Now to find all of the users who are currently online it is just a matter of searching the sessions table for all the users who have been active in the last 10 minutes. This can be done using rails built in session model. Finally the session data needs to be unmarshaled and decoded. This stumped me for a while, but finally I found the answer at http://caboo.se/doc/classes/CGI/Session/ActiveRecordStore/SqlBypass.html. So here is my code to return an array of the member_ids of all the members online and active within the last 10 minutes.
def who_is_online
@whos_online = Array.new()
onlines = CGI::Session::ActiveRecordStore::Session.find( :all, :conditions => [ 'updated_at = ?', Time.now() - 10.minutes ] )
onlines.each do |online|
id = Marshal.load( Base64.decode64( online.data ) )
@whos_online << id[ :member_id ]
end
return @whos_online
end
Trackbacks
Use this link to trackback from your own site.
Thanks for the help
[…] matt-beedle.com » Rails - How to find out who is online (tags: online rails Ruby) […]
i am used rails 1.2.2, but i got error with who_is_online method:
undefined method `unpack’ for { :user=>2, “flash”=>{}, :return_to=>”/”}:Hash
could you know how to fix this?
does anyone sole this unpack pb? I am also facing the same error and it’s very hard to find some info about that on the web.
ok I have done that:
@whos_onlineand it's working.
In fact I dont understand the use of this marshal.load....
Hi, seems like a short and simple approach. But I went into two problems. At first it took me some time to recognize why I never get a single session object. This condition you have there is ‘updated_at = ?’, shouldn’t it be ‘updated_at > ?’, because it’s close to impossible to have one session updated at EXACTLY one timestamp. I couldn’t fix the second problem, which is the same one that Caiwangqin and VzMind faced. It would be really great if someone described VzMind’s solution or an other one.
The error undefined method `unpack’ for { :user=>2, “flash”=>{}, :return_to=>”/”}:Hash is due to the code using
id = Marshal.load( Base64.decode64( online.data ) )
instead of
id = Marshal.load( Base64.decode64( online[’data’]) )
since the return data is a hash array and not an activerecord model
Nice Tip.
Thanks
[…] 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 […]
Great starting guide!
I fixed a couple errors in the above, went into a few more specifics in getting it set up, and describe an implementation that doesn’t need to get mixed up with the performance inefficient-Marshalling stuff:
http://www.williambharding.com/blog/?p=99