Determine if User's online - ruby-on-rails

How can I determine if a user is online or not? Preferably a group of users. I was thinking everytime a user visits a page create a record in the db with Time.now and use AJAX to invoke periodic calls to my remote server; just to see if the time from their last noted activity was about, say, 10 minutes?

You could use Juggernaut to determine if the user if online by "ping" him constantly.

Related

Using sidekiq in rails, how can I send messages to a bunch of users, each of which has a unique time they want to receive it?

Hey I have a rails application and a bunch of users and I want to send them a message once per day at a preferred local time of the user's choice. (A message is a text, email, or chatbot notification.)
I believe I could add something to my User model that would allow for something to be performed every 24 hours at the preferred time but I'm not sure specifically how to implement that AND I also don't know how to remove these jobs from the queue if, for example, the user changes their preferred time or they want to disable messages all together.
Any thoughts on how I could do this?
Where is your application hosted?
You can have a cron task or a scheduler (Heroku) that runs every hour (or every 10 minutes). It would query in a users preferences table searching for users who want to receive the email at this moment (or in a range near this moment, such as the next 10 minutes).
time = Time.now
#users = User.include(:settings).where(“settings.receive_email_at between ? and ?”, time, time + 10.minutes)
You may need some changes to handle timezones and to avoid sending duplicate emails, but that’s just an idea.
It's simple. Build two models - One to store user and its time mapping (UserTimeMapping) and the second one to create a unique entry for each day when a message is sent to user (UserMessage).
Write a cron task which runs every 10 minutes and pulls all the records from UserTimeMapping which are to be executed for next 10 minutes and schedules a worker task for the exact time (say MessageTriggerWorker). The worker has to check in UserMessage table whether a record exists for the given user_id for today and if yes it has to return without performing any task. If that is not the case then it should send the message and create a record in the UserMessage table.

Fetch and refresh Twitter user's friends with Rails

So basically I want to allow my users to connect to my website with Twitter in order to fetch their friends (followings), save these relationships to a table and keep this table updated when there is a change on Twitter (new follow, unfollow).
For the fetch part, I handle it with https://github.com/sferik/twitter. But I don't really know how to get started with the "update" part considering I could have a large users base and Twitter's rate limits. I thought about using a background job and play with rate limits, but it doesn't look like a viable or scalable option.
Any ideas to put me on tracks?
I don't know the twitter api, but it would be magnificent if you could have a webhook that gets to notifications form twitter every time a user of your app gets or looses a follower so that every 100 notifications or so you trigger a background job using active job; although I don't think that's very convenient for twitter either.
If that's not an option maybe you could have a background job for now and have it running on a special dyno or dynos when your users base grows large enough (I can explain myself in heroku terms).

Ruby on Rails Listener

Is there such a thing as a listener in Ruby? I know they have session listeners for JSP, so I was wondering if there was something similar. Ultimately, I would like to create a listener to listen to when session are created or destroyed so I can display a count of how many users are currently online.
You do not know how many users are online on a webserver, unless they have a permanent active connection (for example something like long-polling, comet).
Your best bet is to look into your session store and count the users that are active in the last X minutes.
A listener will not fire reliably when a user disconnects. For example with 'login' and 'logout' logic you will not get all logout actions, because internet connections can fail, users can forget to press the logout button, etcetera.
Update: for Rails, check this forum post: http://railsforum.com/viewtopic.php?id=18480 which explains the solution in more detail.

rails: how to detect other clients browsing the same url

What want to be accomplished is:
I want to "synchronize web browsers". my site has a "wait URL" where when browser gets there it will be kept waiting till another browser also go there and then both will be presented with a quiz-like game.
Right now the wait url will call each second to Rails to check if other player came to the game. How can in the Rails framework detect a different client connecting to the same URL?
As the controller is recreated per request looks like is not the place, not the view for sure and storing this in the model looks really clumsy.
Also, after the pairing I need to check and compare every answer of the paired users so somehow that information must be retained
What you're trying to do is share information between users. So the database or memcached are the most sensible.
Simplest: I'd create an ActiveRecord object, perhaps called Quiz, instances of which people join by virtue of going to a URL, e.g using default routes:
http://yoursite.com/quizes/join/3434
You'd need an ajax poller poller to notify the others; use periodically_call_remote for this -- you could use render :nothing => true by default and render something else if there was an error to keep it efficient. You can also use the frequency method as a basis to determine whether people leave the quiz as well (e.g. if frequency is 1s, then assume someone has left if they didn't ping after 5-10s).
Assuming these users are not registered with the site so don't have some kind of user id you could store I would suggest using the session. It is a per user data store. By default the session is stored in an encrypted cookie on the users machine. However you can use ActiveRecord as the session store and could maybe query that table directly?
Store the URL in the session and do a search for it at a later time. You can normally only access the current users session using the Rails 'session' hash but maybe (untested) if you created a model called Session (or maybe something more specific like 'WaitingGamers') which used the sessions table you could lookup the information you need.
I would guess when using ActiveRecord as the session store the session data is stored as a serialised hash. Use Marshall to turn it back in to a regular hash and find the data you stored in there.
I'm not a rails expert, but since all the state resides in your database that would be the place to keep this information.
You could keep a "waiting users" table, and in the "wait URL" view check if the user is already in the table. If not, add him to the table. Then, check if there is another user waiting (maybe there's more than one?) and if so, match them up and delete them from the table.
Another improvement would be to keep a timestamp for each user in the "waiting users" table, which gets updated in the view - this would serve as a keep-alive that will enable you to detect users that left the "wait URL" page or closed the browser.

How to go about sending email x hours after a user signs up in Ruby on Rails?

How would I go about sending an email to a user, say, 48 hours after they sign up, in Ruby on Rails? Thanks!
As Joseph Daigle mentioned, you need to obviously record the exact date and time the user registered. After that, you need a cron running every certain number of minutes (every hour, for example) checking to see if there's any new users whose registration time is greater than 48 hours, send a mail to said user and mark that user as already emailed, so you don't email them again.
As per the actual mail sending, check out the following documentation page:
http://wiki.rubyonrails.org/rails/pages/HowToSendEmailsWithActionMailer
It has all you need to know to send mails with RoR.
I recommend that you use the latest version of BackgrounDRb to handle this. You can read about BackgrounDRb here: http://backgroundrb.rubyforge.org/
In order to queue a message for later delivery, the BackgrounDRb client code (in your application model's after_create callback, maybe) could look something like this:
MiddleMan(:email_worker).enq_send_email_task(:message => #message,
:job_key => "notify1",
:scheduled_at => Time.now + 48.hours)
You'd have to build a BackgrounDRb worker to handle sending the email:
# RAILS_ROOT/lib/workers/email_worker.rb
class EmailWorker < BackgrounDRb::MetaWorker
set_worker_name :email_worker
def send_email_task(message)
# ... Code to send the email message
end
end
Note that in order to use BackgrounDRb in this way, you have to use persistent job queues, so make sure you run the migration included with BackgrounDRb to set up the persistence table in your application.
BackgrounDRb is started separately from Rails (mongrel, apache, etc) using 'script/backgroundrb start', so make sure that you add the daemon to whatever process monitoring you're using (god, monit, etc) or that you create an /etc/init.d script for it.
First you're going to need a running daemon or background service which can poll your queue (probably from in a database) every few minutes.
The algorithm is pretty simple. Record the time of the user event in the queue. When the daemon checks that item in the queue, and the time difference is greater than 48 hours, prepare the e-mail to send.
You can queue jobs with a delay using async observer. Ideally, anything you have that isn't known to be instant (or very close to it) all the time should pass through something like that.
I wrote a plugin called acts_as_scheduled that may help you out.
acts_as_scheduled allows you to manage
scheduled events for your models.
A good example of this is scheduling
the update of RSS Feeds in a
background process using Cron or
BackgroundRB.
With acts_as_scheduled your schedule
manager can simply call
"Model.find_next_scheduled()" to grab
the next item from the database.
How I would approach this is by creating a scheduling controller, that will query the database for the next_scheduled and then use a mailer to send the message. The you set up a Cron Job to call the controller periodically using WGET or CURL. The advantage of the Cron/Controller approach is that no further infrastructure or configuration is required on the server and you avoid complicated threading code.
I think I'd be inclined to store the need for the email and the earliest time after which it should be sent, somewhere separate, then have my things-to-do task look at that. That way I only have to process as many records as there are emails to be sent, rather than examine every user every time, which would either get tedious or require an otherwise probably unnecessary index. As a bonus, if I had other tasks to be performed on some sort of a diarised basis, the same construct would be useful with little modification.

Resources