8

Lets say I have a cronjob like this:

every 1.day, :at => '4:30 am' do  
  runner "MyModel.task_to_run_at_four_thirty_in_the_morning"  
end  

Although, I would like to make '1.day' more dynamic, such as changing the value via a form in an administration page.

Then it could look like this:

every Constant.find(2).value, :at => '4:30 am' do 

or

@const = Constant.find(2)
every @const.span, :at => @const.time do 

Can anyone come up with an idea on how to make this work?

Obviously, the reason for this would be that I could use the values stored in the database on my site, like an message saying

<%= "The next update is in less than #{@const.time}" #or something similar %>
Frexuz
  • 4,732
  • 2
  • 37
  • 54

4 Answers4

10

Thank you idlefingers! It totally worked. Here's my solution:

require "#{RAILS_ROOT}/config/environment.rb"

@notification_daily = Constant.find_by_key("notification_daily_time_span")
every eval(@notification_daily.value), :at => @notification_daily.additional_data do
  runner "Notification.daily"
end

@notification_weekly = Constant.find_by_key("notification_weekly_time_span")
every eval(@notification_weekly.value), :at => @notification_weekly.additional_data do
  runner "Notification.weekly"
end

.value can contain for example: 1.day or :sunday
.additional_data contains the timestamp, example: 11:00am

And yes, I'm aware that I need to run --update crontab again :)
But I'll let a cronjob update itself, hehe.

Frexuz
  • 4,732
  • 2
  • 37
  • 54
  • That doesn't work for me in Rails4. The require statement doesn't work. any idea what do I need to change? – ShivamD Nov 08 '13 at 23:08
  • 1
    I haven't tried Rails 4 myself yet, but i think RAILS_ROOT is changed to Rails.root. – Frexuz Nov 29 '13 at 20:04
  • @Frexuz : What is this line means, can you help me to get rid of it. notification_weekly = Constant.find_by_key("notification_weekly_time_span") - also what is notification_weekly_time_span – SSR Jun 19 '15 at 06:19
  • @SSR That is just my own model which I can change via my Admin UI. It's a model that has `value` and `additional_data` to be able to generate a Whenever row dynamically. You can fetch any data you want, as long as its value translates to any valid Whenever value. As stated in my answer: `.value` can contain for example: *1.day* or *:sunday* `.additional_data` contains the timestamp, example: *11:00am* – Frexuz Jun 19 '15 at 13:25
  • @Frexuz Thanks for the information. but I am still confused how to achieve this one. can you help me? can you share your code or can you list steps? – SSR Jun 25 '15 at 07:18
  • If you read my question, the only thing I am doing is replaceing `1.day` and `4:30 am` inside `every 1.day, :at => '4:30 am' do` with variables from my application. Only difference is, that `1.day` is a string (from `@notification_daily.value`), so it need an `eval()` around it. – Frexuz Jun 25 '15 at 09:36
  • Thank you for your answer! Can you tell, please , what about "cronjob update itself"? How you finally achieve autoupdating? – Ngoral Jul 05 '18 at 07:38
  • Just create a normal cron job, that runs something like `cd your/app && bundle exec whenever --update-crontab` – Frexuz Jul 05 '18 at 10:58
8

I've never tried, but you should be able to do this by loading up the Rails environment in whenever so that you can use your model classes. Just use require File.dirname(__FILE__) + "./environment" (or "./application" for Rails 3) in your schedule.rb, assuming your schedule.rb is in the config dir.

However, since all whenever does is generate lines in the crontab, any changes made to any Constant would require running whenever --update-crontab again.

idlefingers
  • 31,659
  • 5
  • 82
  • 68
7
# In rails 4
require File.expand_path('../..//config/environment.rb', __FILE__)

# This is your table by which you will get your new value 
bid_update = DynamicOfferTime.first

# Now Task As
every (bid_update.hour_value).hours do
  puts "This will repeat in every #{bid_update.hour_value} hour"
end

Do not forget to update whenever

Mukesh
  • 921
  • 10
  • 23
1

I had the same task and decided to solve it a bit another approach. In my table have a lot of records where storing settings for schedule (daily, monthly, weekly, time)

In schedule.rb file I added a cron job, which was running every day at 00:00 and select the records, which can be run today. And after it added to queue with sidekiq using perform_at.