How to create recurring notifications in Rails from an admin interface? - ruby-on-rails

I would like to create a new function in my survey app that lets users set daily, weekly etc. notifications about the stats of their surveys. Also I would like to let users delete these notifications if they don't need them anymore, or their survey ends.
It seems fairly simple to create a Notification model, which stores the necessary information about the notification, but how do I schedule it to send out the e-mail with the stats daily, weekly ( whatever the user sets ) etc.
Sure I can use delayed_job or resque and reschedule everytime but that doesn't seem like an elegant solution.
Any ideas how to make this happen in the most elegant, and efficient way?

I think you will find whenever gem useful
here's an example syntax for it:
every 3.hours do
runner "MyModel.some_process"
rake "my:rake:task"
command "/usr/bin/my_great_command"
end
every 1.day, :at => '4:30 am' do
runner "MyModel.task_to_run_at_four_thirty_in_the_morning"
end

Related

scheduled tasks in rails

In my rails app I would like to notify the application users at a future time they select on the interface. I am using rufus-scheduler for annual notifications but I don't know how to use it at a specific time a user picks.
Thanks
Please go through on readme of gem:
require 'rufus-scheduler'
scheduler = Rufus::Scheduler.new
scheduler.at '24h' do
# do something at a given point in time
end
So what you can do, you can make a rake task that will run daily and it will check If there is any tomorrow date of action of user to run anything then It can create a delayed job for that time then It will execute
By reading the previous comments i feel you can do the following
1.Write a rake task to get all the notification to be sent on the next day and insert the same into a new table(its should contain notification_id and user_id,status) where you can track it .
2.Run the above rake task every day using rufus scheduler .
3.Write another rake task which will take the notification_id and user_id from the table and send notification via mail or your notification center and then update the status in the table,this also should be scheduled in Rufus scheduler
Hope the flow will be of your help,this approach will give you ability and flexibility on the notification sent and reports based on status can also be generated over notification
You can run a task at a specific time by using scheduler.at. Example:
scheduler.at '2030/12/12 23:30:00' do
# do something at a given point in time
end
See https://github.com/jmettraux/rufus-scheduler for the full details.

Rails: send mail after some time has passed

I have the following scenario:
1. Someone creates a task in Redmine
2. Certain things are done (or not done) with this task
3. In case 3 days have passed since task creation and it is not in the right state, send an email to interested persons.
My question is how do I schedule an email (or the task that will check if an email is required) in exactly three days with Rails? The only option I could think of so far is to create some rake task and run it every couple of minutes. Are there better options?
You've got a couple of options. You probably want to look at Active Job (Rails > 4.2). This lets you schedule a job to run after a specified period:
MyJob.set(wait_until: Time.now + 3.days).perform_later(record)
If you're on a version of rails prior to 4.2 then DelayedJob or Sidekiq or Resque could be used. Active Job is essentially a layer over the top of something like this anyway so a later migration to that shouldn't be too painful.
Alternatively if you don't need to check after exactly 3 days then you could sweep for tasks that need to have emails generated using cron (whenever is a good wrapper for this). You can sweep as often as you want, although every few minutes is probably excessive, and it means you won't have to set up a queueing back end on your server.
It does mean that you'll have to find the tasks that need emails generated for them whereas with the queuing system you'll know exactly which task you're dealing with already. However, it seems like plenty of those tasks won't need an email anyway so it might be more efficient to actively look for the ones that do.
As an alternative you can use https://github.com/resque/resque and https://github.com/zapnap/resque_mailer
Hope this helps.
You can use Whenever to schedule jobs/tasks/method calls ..almost anything
JUST add the gem ...run bundle install..add your code ....update the schedule.rb
for example:
##in schedule.rb
every 5.minutes do
p "============Running rake task Only"
rake "events:notify_user"
end
every 2.hours do
p "============Running rake task and local script as well as calling a method from your code"
command "/usr/bin/some_great_command"
runner "MyModel.some_method"
rake "some:great:rake:task"
end
You can also watch the Railscasts

Best way to manage gem whenever for sending emails

In my application there are posts which are going to expire in certain time of a day.
After the expiration the customer needs to notify through emails.
I have used Rails cron whenever for in each 1 minute and it makes expire the post at the specified time and sends the email to customers.
Schedule.rb
every 1.minutes do
rake "ad_has_expired_task"
end
Will be this a better way?
Any help is appreciated.
Thanks
For small app, this way is good, but for a bigger app, that may keep cpu busy.
Here is a solution from my site.
gem sidekiq
gem whenever
in scheduler.rb
every 1.day do
rake "scan_expired_task"
end
in rake taks scan_expired_task.rake
if post.will_expire_today
MyMailerWoker.perform_async(related_user_ids, post.expired_at-Time.now)
end
Then you write your mailer program in your MyMailerWoker
The codes above can't be executed directly, you need to customize it by your business.
Hope it helps.
reference:
https://github.com/mperham/sidekiq/wiki/Getting-Started

Rails send email on schedule

I have an app that presents a calendar allowing you to create events that display on the calendar. One of the fields you set is the day the event starts. I would like to be able to send email reminders out when the day of the event arrives.
I'm new to rails so I'm not exactly sure what I need or where to start. I read the rails guide for ActionMailer and generated a mailer, I was assuming I would need one of those. I also read the rails guide for observers and thought maybe that might be a route to what I want to accomplish.
Let's say every day, 7 days a week at 9am central, a job (cron or rake task) should run that searches the 'start_at' column of every Event in the database (sqlite locally, Postegre with heroku in production) and if the start_date is equal to 'today?' then send the action mailer template to remind the user.
So what's the best way to (and with what tool) to build a job to examine that database and kick off emails every day? In the future I guess this would grow to reminders ahead of time.
Some pseudo-code:
def send_email
if self.start_at == Date.today #assuming self.start_at.today? works too.
// send email
end
Just not sure how to get that working.
You could have a Controller/Action that does it, then call the url from a cron job on a specified schedule using a command like cURL.

How to have users create scheduled tasks in rails app deployed on Heroku

I have a rails app deployed on Heroku. I want to add a feature that enables users of the app to set a reminder. I need some way for the app to schedule sending an email at the time specified by the user.
I have found numerous posts referring to using delayed_job for this, but none of the write-ups / tutorials / etc. that I have found directly address what I am trying to accomplish (the descriptions I have found seem more geared towards managing long-running jobs that are to be run "whenever").
Am I on the right track looking at delayed_job for this? If so, can somebody point me towards a tutorial that might help me?
If delayed_job is not quite right for the job, does anybody have a suggestion for how I might approach this?
The most typical way of handling this is to use a cron job. You schedule a job to run every 15 minutes or so and deliver any reminders that come up in that time. Unfortunately, heroku only allows cron jobs to run every hour, which usually isn't often enough.
In this case, I'd use delayedjob and trick it into setting up a recurring task that delivers the notifications as often as necessary. For example, you could create a function that begins by rescheduling itself to run in 10 minutes and then goes on to send any reminders that popped up in the previous 10 minutes.
To view delayedjobs send_at syntax to schedule future jobs check here: https://github.com/tobi/delayed_job/wiki
ADDED after comments:
To send the reminder, you would need to create a function that searches for pending reminders and sends them. For example, let's say you have a model called Reminder (rails 3 syntax cause I like it better):
def self.find_and_send_reminders
reminders = Reminder.where("send_at < ? AND sent = ?", Time.now, false).all
reminders.each do |r|
#the following delayed_job syntax is apparently new, and I haven't tried it. came from the collective_idea fork of delayed_job on github
Notifier.delay.deliver_reminder_email(r)
#I'm not checking to make sure that anything actually sent successfully here, just assuming they did. may want to address this better in your real app
r.update_attributes!(:sent => true)
end
#again using the new syntax, untested. heroku may require the old "send_at" and "send_later" syntax
Reminder.delay(:run_at => 15.minutes.from_now).find_and_send_reminders
end
This syntax assumes you decided to use the single reminder entry for every occurence method. If you decide to use a single entry for all recurring reminders, you could create a field like "last_sent" instead of a boolean for "sent" and use that. Keep in mind these are all just ideas, I haven't actually taken the time to implement anything like this yet so I probably haven't considered all the options/problems.
Check out the runt gem, may be useful for you: http://runt.rubyforge.org/
You can use delayed_job's run_at to schedule at a specific time instead of whenever.
If your application allows the users to change the time of the reminders you need to remember the delayed_job to be able to update it or delete it when required.
Here is more details.
It's good to avoid polling if you can. The worker thread will poll at the database level, you don't want to add polling on top of polling.

Resources