如何随时检测内部的Rails环境

Posted

技术标签:

【中文标题】如何随时检测内部的Rails环境【英文标题】:How to detect Rails environment inside whenever 【发布时间】:2011-10-28 09:49:18 【问题描述】:

如果您了解用于创建 cron 作业的 whenever gem,这个问题可能才有意义。

对于我的应用,我想在所有环境中使用whenever,包括测试开发。 我的schedule.rb 看起来像这样:

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

但它在Rails.env.to_sym 上失败(同样代表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>'

所以,我的问题基本上可以归结为:

    如何访问当前环境, 我应该怎么做才能在所有环境中使用whenever

【问题讨论】:

【参考方案1】:

至少在更新版本中,只要可以使用@environment 访问环境。例如,如果您希望只为生产中的某些作业生成 cron 条目:

case @environment
when 'production'
  every 1.day, :at => '0:00 am' do
    rake "some:task"
  end 
end

【讨论】:

就我而言,这告诉我production 而不是development,而@JCoster22 的解决方案运行良好(在开发中进行开发,在生产中进行生产) @environment 变量即使在开发环境中也是“生产”?听起来很糟糕 @MattiasWadman:是的,默认环境是生产环境。我使用bundle exec whenever --set "environment=development" 来覆盖它。【参考方案2】:

错误消息表明 Rails 未定义。即当您询问rails运行的环境是什么时,没有加载框架。

事实上,从查看代码的角度来看,它看起来像 rails 并不是它的必需品(即,您可以在没有安装 rails 的情况下安装和运行任何时候)。因此,无论何时都无法查看您的 Rails 环境(据我所知)

【讨论】:

【参考方案3】:

作为recommended by the gem author,解决方法是pass in the current environment as a variable:

$ 每当 --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:活动:同步 --silent >> /home/marius/uxolo/log/cron.log 2>> /home/marius/uxolo/log/error.log'

$ 每当 --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:活动:同步 --silent >> /home/marius/uxolo/log/cron.log 2>> /home/marius/uxolo/log/error.log'

Chris Bailey 是对的:Whenever 本身不加载 Rails 环境。

【讨论】:

【参考方案4】:

a similar question 的第一个答案的变体对我有用。添加

require File.expand_path(File.dirname(__FILE__) + "/../config/environment")

schedule.rb 的顶部,您就可以调用 Rails.env 来访问当前的 Rails 环境。

注意:如果您的environment.rb 文件不在/app/config 中,则上述路径会有所不同

【讨论】:

【参考方案5】:

我取了Rails.env的实现我找到了here(通过点击“source”),并用它来初始化::Rails开头的config/schedule.rb模块

eval %Q(module ::Rails
  def self.env
    '#@environment' || ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development"
  end
end
)

这将创建Rails 模块,并使其环境返回您在whenever 命令行中提供的--set environment=... 内容,正如脚本作者所建议的那样。

但是,无论何时将@environment 默认设置为生产,所以这个大的“或”可能不是很有用。

现在,无论何时脚本中的 Rails.env 调用都可以正常工作。对我来说更重要的是,它也适用于我包含在 schedule.rb 中的其他脚本,例如加载了 application.yml 的脚本。

附: eval 调用用于从模块定义中访问schedule.rb 脚本范围内可用的@environment

【讨论】:

以上是关于如何随时检测内部的Rails环境的主要内容,如果未能解决你的问题,请参考以下文章

如何检测当前按下的键?

在 Rails 4 生产环境中找不到资产的 404 错误

Java 运行时环境检测到一个致命错误:内部错误;错误:ShouldNotReachHere()

如何快速正确的安装 Ruby,Rails 运行环境

如何从 Rails 中访问 Rack 环境?

如何列出 Rails 3 应用程序中所有定义的环境?