How to detect Rails environment inside whenever
This question will probably only make sense if you know about the whenever gem for creating cron jobs.
For my app, I want to use whenever
in all the environments, including testing and development.
schedule.rb
looks like this:
set :output, {
:error => "#{path}/log/error.log",
:standard => "#{path}/log/cron.log"
}
set :environment, Rails.env.to_sym
every 5.minutes do
rake 'db:activity:synchronize'
end
but it fails on Rails.env.to_sym
(and the same stands for RAILS_ENV
):
/home/marius/.rvm/gems/ruby-1.9.2-p290@uxolo/gems/whenever-0.6.8/lib/whenever/job_list.rb:21:in `eval': uninitialized constant Whenever::JobList::Rails (NameError)
from /home/marius/.rvm/gems/ruby-1.9.2-p290@uxolo/gems/whenever-0.6.8/lib/whenever/job_list.rb:21:in `eval'
from /home/marius/.rvm/gems/ruby-1.9.2-p290@uxolo/gems/whenever-0.6.8/lib/whenever/job_list.rb:21:in `initialize'
from /home/marius/.rvm/gems/ruby-1.9.2-p290@uxolo/gems/whenever-0.6.8/lib/whenever.rb:15:in `new'
from /home/marius/.rvm/gems/ruby-1.9.2-p290@uxolo/gems/whenever-0.6.8/lib/whenever.rb:15:in `cron'
from /home/marius/.rvm/gems/ruby-1.9.2-p290@uxolo/gems/whenever-0.6.8/lib/whenever/command_line.rb:41:in `run'
from /home/marius/.rvm/gems/ruby-1.9.2-p290@uxolo/gems/whenever-0.6.8/lib/whenever/command_line.rb:8:in `execute'
from /home/marius/.rvm/gems/ruby-1.9.2-p290@uxolo/gems/whenever-0.6.8/bin/whenever:38:in `<top (required)>'
from /home/marius/.rvm/gems/ruby-1.9.2-p290@uxolo/bin/whenever:19:in `load'
from /home/marius/.rvm/gems/ruby-1.9.2-p290@uxolo/bin/whenever:19:in `<main>'
So, my question basically boils down to:
- How do I access the current environment, or
- What should I do to use
whenever
in all the environm开发者_如何学编程ents?
At least in newer version of whenever it is possible to access the environment with @environment
. For example if you want whenever to only generate cron entries for some jobs in production:
case @environment
when 'production'
every 1.day, :at => '0:00 am' do
rake "some:task"
end
end
The error message suggests that Rails isn't defined. i.e the framework isn't loaded when you're asking the question what environment is rails running with.
In fact from looking at the code for Whenever it looks like rails isn't a requirement for it (i.e. You can install and run Whenever without rails even being installed on your system). Hence there's no way for Whenever to look at your rails environment (as far as i can tell)
As recommended by the gem author, the solution is to pass in the current environment as a variable:
$ whenever --set environment=test 0,5,10,15,20,25,30,35,40,45,50,55 * * * * /bin/bash -l -c 'cd /home/marius/uxolo && RAILS_ENV=test rake db:activity:synchronize --silent >> /home/marius/uxolo/log/cron.log 2>> /home/marius/uxolo/log/error.log' $ whenever --set environment=development 0,5,10,15,20,25,30,35,40,45,50,55 * * * * /bin/bash -l -c 'cd /home/marius/uxolo && RAILS_ENV=development rake db:activity:synchronize --silent >> /home/marius/uxolo/log/cron.log 2>> /home/marius/uxolo/log/error.log'
And Chris Bailey is right: Whenever
itself doesn't load the Rails environment.
A variation of the first answer to a similar question worked for me. Add
require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
to the top of schedule.rb
and you'll be able to call Rails.env to access the current Rails environment.
Note: the above path would be different if your environment.rb
file isn't in /app/config
I took the implementation of Rails.env
I found here (by clicking on "source"), and used it to initialize the ::Rails
module at the beginning of the config/schedule.rb
eval %Q(module ::Rails
def self.env
'#{@environment}' || ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development"
end
end
)
This creates the Rails
module, and makes its environment return what you supplied as --set environment=...
in the whenever
command line, as the script author suggests.
However, whenever sets the @environment
to production by default, so this large "or" may be not quite useful.
Now the Rails.env
call in the Whenever script would work. What was more important in my case, it also worked in other scripts I included into schedule.rb
, such as the one that loaded application.yml
.
P.S. The eval
call is used to access @environment
available in the scope of the schedule.rb
script from inside the definition of a module.
精彩评论