开发者

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.

My 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:

  1. How do I access the current environment, or
  2. 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜