No More Crontab Madness with a single Night Rake-Task

Crontab grows larger and larger with every new cleanup/maintence task…

...
0 0 1 * * cd ~/apps/my_app/current && RAILS_ENV=production rake summary:weekly_update >> ~/apps/my_app/current/log/summary_weekly_update.log
0 0 7 * * cd ~/apps/my_app/current && RAILS_ENV=production rake summary:weekly_update >> ~/apps/my_app/current/log/summary_weekly_update.log
0 0 14 * * cd ~/apps/my_app/current && RAILS_ENV=production rake summary:weekly_update >> ~/apps/my_app/current/log/summary_weekly_update.log
0 0 21 * * cd ~/apps/my_app/current && RAILS_ENV=production rake summary:weekly_update >> ~/apps/my_app/current/log/summary_weekly_update.log
...
echo 'crontab sucks...'

This is not DRY, so we fix it…

Cron calls “rake night” every night and night takes care of the rest…

#redirect and append puts to the logfile
def logging_to(path)
  FileUtils.touch([path])
  $stdout = File.new(path,'a+')
  yield
  $stdout = STDOUT
end

#use DRY to simulate a dry run
#uses hoptoad for error recording(better than exception notifier...), get it @ hoptoad.com
def invoke_and_log_task(name)
  begin
    logging_to "log/#{name.gsub(':','_')}.log" do
      if ENV['DRY']
        puts "dry-running #{name}"
      else
        Rake::Task[name].invoke
      end
    end
  rescue Exception => e
    HoptoadNotifier.notify(
      :error_class => "Nightly #{name} Error #{e.class}",
      :error_message => "#{e.message}"
    )
  end
end

desc "Runs maintains tasks at night"
task :night do
  invoke_and_log_task 'feed:update'
  invoke_and_log_task 'summary:weekly_update' if [1,7,14,21].include? Time.now.day
  ENV['greeting'] = 'Hello again...'
  invoke_and_log_task 'spam_users' if Time.now.day == 5
end