How to trigger a rake task using whenever in Rails - ruby-on-rails

I am writing a Rake task. I want to trigger it every last sunday of every month at 11 pm.
How can I schedule this using the Whenever gem in Ruby on Rails?
I have my rake task in the following location: app/lib/tasks/my_task.rake
task :create_entries => :environment do
puts "Hello"
end

I don't think there's a rule for "last x day of the month" but you can always put an extra if test inside the block:
every :sunday, :at => '11pm' do
#if the month is different a week from now, we must be in the last
#sunday of the month
if Time.now.month != 1.week.from_now.month
rake "my:rake:task"
end
end
So, this scheduled code will run every sunday, but it will only go on to call the rake task if the time meets the further conditions.

Related

Schedule a task to work on 15th and the last day of the month in ruby

I have defined a rake task to work on the 15th and last day of the month at 8 am in schedule.rb file. I just wanted to confirm if I have done it the right way. Please have a look and suggest it.
run this task at 8am on 15th of every month
every '0 8 15 * *' do
rake 'office:reminder', environment: ENV['RAILS_ENV']
end
run this task at 8am on the last day of every month
every '0 8 28-31 * *' do
rake 'office:reminder', environment: ENV['RAILS_ENV']
end
cron usually doesn't allow to specify "last day of the month". But in Ruby, you can simply use -1 to denote the month's last day:
Date.new(2020, 2, -1)
#=> Sat, 29 Feb 2020
So instead of having separate entries for specific days, you could define one entry running every day at 8am and pass the days as arguments to the rake task:
every '0 8 * * *' do
rake 'office:reminder[15,-1]', environment: ENV['RAILS_ENV']
end
Then weithin your task, you can turn these arguments into date objects and check if any of them is equal to today's date:
namespace :office do
task :reminder do |t, args|
days = args.extras.map(&:to_i)
today = Date.today
if days.any? { |day| today == Date.new(today.year, today.month, day) }
# send your reminder
end
end
end
Since cron has a very simple interface it's hard to convey a concept like "last day of month" to it without outside help. But you could shift your logic into the task:
every '0 8 28-31 * *' do
rake 'office:end_of_month_reminder', environment: ENV['RAILS_ENV']
end
And in a new task called office:end_of_month_reminder:
if Date.today.day == Date.today.end_of_month.day
#your task here
else
puts "not the end of the month, skipping"
end
You would still have your first-of-the-month task. But if you wanted to roll it into one:
every '0 8 15,28-31 * *' do
rake 'office:reminder', environment: ENV['RAILS_ENV']
end
And in your task:
if (Date.today.day == 15) || (Date.today.day == Date.today.end_of_month.day)
#your task here
else
puts "not the first or last of the month, skipping"
end

how can i trigger a rake task on every 4th sunday of every month in rails?

i am having a rake task. i want that task to be scheduled to run on every 4th Sunday of every month. i am using whenever gem. how can i define logic in config/schedule.rb so that it will run on every 4th Sunday of every month in Rails? please help me.
this is my rake task app/lib/tasks/my_task.rake.
task :do_something => :environment do
end
this is my code in config/schedule.rb
every :sunday, :at => '12pm' do
runner "Employee.make_checkin_out"
end
how can i change the above logic?
whenever gem gives a facility to generate a cron job. This is a scheduler for rake tasks. You can define like
every 1.month, :at => '4:30 am' do
runner "MyModel.task_to_run_at_four_thirty_morning_every_month"
end
If you want something like 1st sunday every month use cron editor like
0 12 1-7 * * [ "$(date '+\%a')" = "Sun" ]

rails whenver gem , running a command only if certain condition passes.

We are using whenever gem with rails on our project. I understand that we can schedule a command using whenever gem like this.
every 1.day, :at => '6:00 am' do
command "echo 'hello'"
end
but my problem is that i want to execute this command only when some condition is met. something like this.
every 1.day, :at => '6:00 am' do
if User.any_new_user?
command "echo 'hello'"
end
end
how can we achieve this with the whenever and rails?
One possible solution i can think of is that i create a runner for this and check that condition there.Something like:
every 1.day, :at => '6:00 am' do
runner "User.say_conditional_hello"
end
and inside my user model:
def self.say_conditional_hello
`echo "Hello"`
end
Any suggestions on this approach or any new approach will be really helpful.
Thanks in advance!.
if you want to only schedule the task if the condition is true then I don't think its possible you can schedule a task then when its time for running the task, the code can decide if it should be run or not, depending on your conditions
One possible solution i can think of is that i create a runner for this and check that condition there.Something like:
Yes this is one way of handeling this, however IMO the best behavior when using whenever is creating a rake task that checks for conditions then executes your code or perform your job
Something like:
Rake Task
namespace :user do
desc "description"
task check_for_new: :environment do
if User.any_new_user?
# code
end
end
end
in your schedule.rb file
every 1.day, :at => '6:00 am' do
rake "user:check_for_new"
end

Erase records every 60 days

I need to erase records in my offers models if the record has more that 60 days from the created_at date.
I only found information about how to populate my model with a rake task, but I couldn't find information about how to make a rake task to delete records. So I just wonder if I have to do this with a task or if rails has something else to do this.
Create a file for the task:
# lib/tasks/delete_old_records.rake
namespace :delete do
desc 'Delete records older than 60 days'
task :old_records => :environment do
Model.where('created_at < ?', 60.days.ago).each do |model|
model.destroy
end
# or Model.delete_all('created_at < ?', 60.days.ago) if you don't need callbacks
end
end
Run with:
RAILS_ENV=production rake delete:old_records
Schedule it to run with cron (every day at 8am in this example):
0 8 * * * /bin/bash -l -c 'cd /my/project/releases/current && RAILS_ENV=production rake delete:old_records 2>&1'
You can also use the whenever gem to create and manage your crontab on deploys:
every 1.day, :at => '8:00 am' do
rake "delete:old_records"
end
Learn more about the gem on Github.
60.days.ago generates a timestamp like
Fri, 08 Aug 2014 15:57:18 UTC +00:00
So you'd need to use < to look for records older(less) than the timestamp.
Online.delete_all("created_at < '#{60.days.ago}'")
It's just a slight oversight by Unixmonkey.
I'd also use the delete_all instead of looping each iterating in a block.
You can create a rake task to delete expired offers , or create class method for your offers model and call it using, for example, whenever gem.
You can delete all records older than 60 days in a single query like so:
Model.where("created_at < '#{60.days.ago}'").delete_all

Rails 3.2 - Rake Background Task Create DB Records

I want to create a rake task that will run automatically every seven days (sunday at midnight), that will analyse a weeks worth of data (at max 20,000 records per week).
An Outlet has_many :monitorings
A Monitoring belongs_to :outlet
I want to check if at the end of the week an outlet has had a minimum of 4 records created. If not, I want a record to be created inside of the DB in a table called unmonitored.
The record should contain the the number of times it has been monitored and the week start and end dates.
To run a rake task periodically, you can use bare cron jobs or a nice ruby wrapper, Whenever.
Take a look:
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
every :hour do # Many shortcuts available: :hour, :day, :month, :year, :reboot
runner "SomeModel.ladeeda"
end
every :sunday, :at => '12pm' do # Use any day of the week or :weekend, :weekday
runner "Task.do_something_great"
end
every '0 0 27-31 * *' do
command "echo 'you can use raw cron syntax too'"
end

Resources