【问题标题】:Correct Ruby on Rails 3 replacement for ENV["RAILS_ENV"] ||= 'production'?正确的 Ruby on Rails 3 替换 ENV["RAILS_ENV"] ||= 'production'?
【发布时间】:2026-02-07 20:20:19
【问题描述】:

我们正在升级到 Ruby on Rails 3(就像现在世界的一半),并且我一直在努力替换 RAILS_ENV 的用法,例如

RAILS_ENV == 'wibble'
# becomes
Rails.env.wibble?

但我不确定该怎么做:

ENV["RAILS_ENV"] ||= 'production'

我们把它放在一大堆Rake 任务和守护进程的顶部,想法是你可以在命令行上传递RAILS_ENV,但如果不是,它默认为“生产”通过了。

我不确定新的适合 Rails3 的方式来执行此操作。所以现在我的rails:upgrade:check 强烈抱怨 Rails2-ishness 的这种入侵......

我不知道:

::Rails.env ||= 'production'

会起作用的。

Rails.env 是否存在于守护进程中?

它是否会自动预先填充命令行中传递的 RAILS_ENV 的值,还是我们需要一种调用守护程序的新方法?

什么是正确的口头禅?


更新:

查看Rails.env 的源代码,

def env
  @_env ||= ActiveSupport::StringInquirer.new(RAILS_ENV)
end

我们可以推断出很多东西。

首先,看起来RAILS_ENV 确实仍然存在——这意味着它可以被设置并且Rails.env 会找到它...

如果 Rails 在守护进程的上下文中是有效的,那么就不需要再做任何事情了。如果不是 - 那么我就不会太在意并像以前一样使用旧的RAILS_ENV

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3


    【解决方案1】:

    Rails.env 实际上是ActiveSupport::StringInquirer 类型,它覆盖method_missing 以提供良好的相等语法。检查:http://api.rubyonrails.org/classes/ActiveSupport/StringInquirer.html

    所以,如果你想通过默认将其覆盖为“生产”,你应该写:

    Rails.env ||= ActiveSupport::StringInquirer.new('production')
    

    但是,您必须检查 Rails.env 的未初始化值,我不确定它是否真的是 nil

    IMO 最好的做法是在所有脚本前加上 env RAILS_ENV=production

    【讨论】:

    • 啊 - 现在这很有用,所以“env(RAILS_ENV)”是你现在手动设置和环境变量的方式吗?
    • g 刚刚查看了 Rails.env 的源代码 - 现在已添加到问题中...
    【解决方案2】:

    编辑lib/tasks/environments.rake

    # Sets environments as needed for rake tasks
    %w[development production staging].each do |env|
      desc "Runs the following task in the #{env} environment" 
      task env do
        Rails.env = env
      end
    end
    
    task :testing do
      Rake::Task["test"].invoke
    end
    
    task :dev do
      Rake::Task["development"].invoke
    end
    
    task :prod do
      Rake::Task["production"].invoke
    end
    

    Source

    更新

    pass RAILS_ENV=production 通过命令行,类似这样:

    RAILS_ENV=production rake db:setup

    this 有帮助吗:

    # before
    if RAILS_ENV == 'production'
      ...
    
    # Rails 3
    if Rails.env.production?
    

    【讨论】:

    • 好吧,请原谅我的无知,但是:1)你将如何调用任务以及 2)这将如何影响守护进程(在我们的例子中,守护进程不是通过 rake 调用的)。
    • 哦...并且只是通过:3)这个解决方案如何符合我们的要求“如果没有在命令行上传递任何内容,则默认为生产,否则允许我们覆盖它,如果我们确实在命令行上传递了一些东西”?
    • 嗨 - 是的,这解释了如何使用 rake 任务......但是我们的守护进程呢?
    • 好的,深入了解您从中获取此代码的帖子 - 我不得不说它可能根本不适合我。您借用的 environment.rake 代码 - 来自某人的自定义 rake 环境。它涵盖为 rake 任务设置环境。
    • 您提供的第二段代码 - 直接来自我已经使用过的文档。正如我所指定的 - 我已经更新了我们的代码以在我们所有常用代码中使用 Rails.env 而不是 RAILS_ENV。
    【解决方案3】:
    if Rails.env.production?
      puts '...'
    

    【讨论】:

    • 恐怕你误解了要求。我不想知道我是否在生产环境中。我想强制我的脚本默认在生产环境中运行。