【问题标题】:Is it possible to set ENV variables for rails development environment in my code?是否可以在我的代码中为 Rails 开发环境设置 ENV 变量?
【发布时间】:2011-06-22 03:33:24
【问题描述】:

我知道我可以通过 bash 设置我的 ENV 变量

export admin_password = "secret"

但是有没有办法在我的 Rails 源代码中的某个地方做到这一点?我的第一次尝试是在environment/development.rb

ENV['admin_password'] = "secret"

但它没有用。有没有办法做到这一点?

【问题讨论】:

  • 请注意,bash 命令应该是export admin_password="secret",而不是export admin_password = "secret"

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


【解决方案1】:

系统环境和rails的环境是不同的东西。 ENV 让你使用 rails 的环境,但如果你想做的是在运行时改变系统的环境,你可以用反引号括住命令。

# ruby code
`export admin_password="secret"`
# more ruby code

【讨论】:

  • 请注意export 会抱怨空格;试试export admin_password="secret"
  • 我忘记了那个(非常重要的)细节。更正了我的答案,谢谢!
  • 这不起作用,因为反引号会产生一个子shell,并且您在子shell中设置的变量不会影响父级的环境。
  • 不,它确实有效。正如明确解释的那样,答案不是针对父母的环境。有非常好的答案可以指导如何做到这一点。
【解决方案2】:

[更新]

虽然“旧答案”下的解决方案适用于一般问题,但本部分将在您的评论澄清后回答您的具体问题。

您应该能够完全按照您在问题中指定的方式设置环境变量。例如,我有一个使用 HTTP 基本身份验证的 Heroku 应用程序。

# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  protect_from_forgery
  before_filter :authenticate

  def authenticate
    authenticate_or_request_with_http_basic do |username, password|
      username == ENV['HTTP_USER'] && password == ENV['HTTP_PASS']
    end
  end
end

# config/initializers/dev_environment.rb
unless Rails.env.production?
  ENV['HTTP_USER'] = 'testuser'
  ENV['HTTP_PASS'] = 'testpass'
end

所以在你的情况下你会使用

unless Rails.env.production?
  ENV['admin_password'] = "secret"
end

不要忘记重新启动服务器,以便重新加载配置!

[旧答案]

对于应用范围的配置,您可以考虑如下解决方案:

创建一个文件config/application.yml,其中包含您希望能够访问的选项的哈希:

admin_password: something_secret
allow_registration: true
facebook:
  app_id: application_id_here
  app_secret: application_secret_here
  api_key: api_key_here

现在,创建文件config/initializers/app_config.rb 并包含以下内容:

require 'yaml'

yaml_data = YAML::load(ERB.new(IO.read(File.join(Rails.root, 'config', 'application.yml'))).result)
APP_CONFIG = HashWithIndifferentAccess.new(yaml_data)

现在,您可以在应用程序的任何位置访问APP_CONFIG[:admin_password],以及您的所有其他数据。 (请注意,由于初始化程序包含 ERB.new,因此您的 YAML 文件可以包含 ERB 标记。)

【讨论】:

  • 好吧,我正在使用 Heroku,它们允许您为不希望签入源代码控制的密码等设置一些 ENV 变量。我试图找出在我的开发机器上做的最好的事情。是的,我正在尝试使用我的应用程序中的数据。
  • 很高兴听到这个消息!如果您认为答案是正确的,您应该通过检查问题旁边的复选标记来标记它。它将为您和回答者赢得声誉,并帮助将来找到此问题的人找到正确答案。
  • 哦,是的,我是新用户,所以我要等 19 个小时才能检查它。还有 3 个小时的时间 :) 但感谢您的帮助!实际上,如果您在删除 dev_environment.rb 代码并用我的代码替换它时编辑您的答案,我很乐意将您的答案标记为更彻底。
  • 我喜欢这个,但由于某种原因(rails 3 v 4?)无法加载 app_config.rb。我将代码放入 config/environment.rb 并获得了相同的效果。 # 加载 rails 应用 require File.expand_path('../application', FILE) require 'yaml' yaml_data = YAML::load(ERB.new(IO.read(File.join(Rails .root, 'config', 'local_env.yml'))).result) APP_CONFIG = HashWithIndifferentAccess.new(yaml_data) # 初始化rails应用 Rails3::Application.initialize!
  • 很抱歉打开这么一个旧线程,但在config/environments/development.rb 文件中特定于开发环境的设置不是更有意义吗?
【解决方案3】:

我在我的问题中尝试这样做的方式确实有效!

# environment/development.rb

ENV['admin_password'] = "secret" 

我只需要重新启动服务器。我认为在 Rails 控制台中运行 reload! 就足够了,但我还必须重新启动 Web 服务器。

我选择自己的答案是因为我觉得这是放置和设置 ENV 变量的更好地方

【讨论】:

  • 很高兴您发现它为什么不起作用!我个人喜欢保存 config/application.rbconfig/environments/*.rb 用于设置 Rails 环境并使用其他方法设置我的 application 环境,但这当然不意味着这是唯一的方法(甚至是“正确”的方法:)
  • 我有点被甩了,因为我试图在生产和开发之间设置不同的东西。但现在我完全同意你的看法!感谢您不仅回答了我最初的问题,还帮助我更好地理解了 Rails 应用程序结构!
【解决方案4】:

Never hardcode sensitive information (account credentials, passwords, etc.)。相反,创建一个文件将该信息存储为环境变量(键/值对),并将该文件从源代码管理系统中排除。例如,就 Git(源代码管理系统)而言,通过将其添加到 .gitignore 来排除该文件:

-bash> echo '/config/app_environment_variables.rb' >> .gitignore 

/config/app_environment_variables.rb

ENV['HTTP_USER'] = 'devuser'
ENV['HTTP_PASS'] = 'devpass'

同样,在/config/environment.rbrequire 行和Application.initialize 行之间添加以下行:

# Load the app's custom environment variables here, so that they are loaded before environments/*.rb
app_environment_variables = File.join(Rails.root, 'config', 'app_environment_variables.rb')
load(app_environment_variables) if File.exists?(app_environment_variables)

就是这样!

正如上面的评论所说,通过这样做,您将在environments/*.rb 之前加载您的环境变量,这意味着您将能够在这些文件中引用您的变量(例如environments/production.rb)。与将环境变量文件放在 /config/initializers/ 中相比,这是一个很大的优势。

app_environment_variables.rb 内部,没有必要区分开发生产的环境,因为您永远不会将此文件提交到您的源代码管理系统中,因此它是默认情况下用于 development 上下文。但是,如果您需要为 test 环境(或在您测试 production 模式 locally 的场合)设置一些特殊的东西,只需添加一个条件块下面所有其他变量:

if Rails.env.test?
  ENV['HTTP_USER'] = 'testuser'
  ENV['HTTP_PASS'] = 'testpass'
end

if Rails.env.production?
  ENV['HTTP_USER'] = 'produser'
  ENV['HTTP_PASS'] = 'prodpass'
end

每当您更新app_environment_variables.rb 时,请重新启动应用服务器。假设您使用的是 Apache/Passenger 或 rails server 之类的:

-bash> touch tmp/restart.txt

在你的代码中,引用环境变量如下:

def authenticate
  authenticate_or_request_with_http_basic do |username, password|
    username == ENV['HTTP_USER'] && password == ENV['HTTP_PASS']
  end
end

请注意,在app_environment_variables.rb 中,您必须将booleans数字 指定为字符串(例如ENV['SEND_MAIL'] = 'false' 而不仅仅是false,以及ENV['TIMEOUT'] = '30' 不仅仅是30),否则你会分别得到can't convert false into Stringcan't convert Fixnum into String 的错误。

存储和共享敏感信息

要打结的最后一个结是:如何与您的客户和/或合作伙伴分享这些敏感信息?您的客户和/或合作伙伴恢复网站的全部运营?),您的客户和/或合作伙伴需要知道您的应用所需的所有凭据。通过电子邮件/Skype 发送这些东西是不安全的,并且会导致混乱。将其存储在共享的 Google Docs 中还不错(如果每个人都使用 https),但是专门用于存储和共享密码等小知识的应用程序将是理想的。

如何在 Heroku 上设置环境变量

如果您在 Heroku 上只有一个环境:

-bash> heroku config:add HTTP_USER='herouser'
-bash> heroku config:add HTTP_USER='heropass'

如果您在 Heroku 上有 multiple environments

-bash> heroku config:add HTTP_USER='staguser' --remote staging
-bash> heroku config:add HTTP_PASS='stagpass' --remote staging

-bash> heroku config:add HTTP_USER='produser' --remote production
-bash> heroku config:add HTTP_PASS='prodpass' --remote production

工头和 .env

Many developers use Foreman(与Heroku Toolbelt 一起安装)到run their apps locally(与使用Apache/Passenger 或rails server 等类似)。 Foreman 和 Heroku 使用Procfile for declaring what commands are run by your application,因此从本地开发人员到 Heroku 的过渡在这方面是无缝的。我在每个 Rails 项目中都使用 Foreman 和 Heroku,所以这种便利性非常好。但事情是这样的.. Foreman loads environment variables stored in /.env via dotenv 但不幸的是dotenv essentially only parses the file for key=value pairs;这些对不会立即成为变量,因此您不能引用已经设置的变量(以保持干燥),也不能在其中执行“Ruby”(如上面的条件语句所述),您可以在/config/app_environment_variables.rb 做。例如,在保持干燥方面,我有时会这样做:

ENV['SUPPORT_EMAIL']='Company Support <support@company.com>'
ENV['MAILER_DEFAULT_FROM'] = ENV['SUPPORT_EMAIL']
ENV['MAILER_DEFAULT_TO']   = ENV['SUPPORT_EMAIL']

因此,我使用 Foreman 在本地运行我的应用程序,但我不使用它的 .env 文件来加载环境变量;相反,我将 Foreman 与上述 /config/app_environment_variables.rb 方法结合使用。

【讨论】:

  • 我喜欢这个解决方案,因为我想确保敏感设置(API 密钥等)在密钥库中得到充分保护,而不是明文并且不与 Git 存储库捆绑。谢谢。
【解决方案5】:

除了这里的解决方案,如果您使用某些开发服务器,还有更简洁的替代方案。

使用 Heroku 的 Foreman,您可以在 .env 文件中创建每个项目的环境变量:

ADMIN_PASSOWRD="secret"

使用Pow,您可以使用.powenv 文件:

export ADMIN_PASSOWRD="secret"

【讨论】:

    【解决方案6】:

    我认为最好的方法是将它们存储在一些 yml 文件中,然后在初始化文件中使用此命令加载该文件

    APP_CONFIG = YAML.load_file("#{Rails.root}/config/CONFIG.yml")[Rails.env].to_hash
    

    您可以轻松访问与环境相关的配置变量。

    你的 Yml 文件键值结构:

    development:
      app_key: 'abc'
      app_secret: 'abc'
    
    production:
      app_key: 'xyz'
      app_secret: 'ghq'
    

    【讨论】:

      【解决方案7】:

      用于加载自定义.env 文件的脚本: 将以下行添加到/config/environment.rb,在require 行和Application.initialize 行之间:

      # Load the app's custom environment variables here, so that they are loaded before environments/*.rb
      
      app_environment_variables = File.join(Rails.root, 'config', 'local_environment.env')
      if File.exists?(app_environment_variables)
        lines = File.readlines(app_environment_variables)
        lines.each do |line|
          line.chomp!
          next if line.empty? or line[0] == '#'
          parts = line.partition '='
          raise "Wrong line: #{line} in #{app_environment_variables}" if parts.last.empty?
          ENV[parts.first] = parts.last
        end
      end
      

      config/local_environment.env(你会想.gitignore它)看起来像:

      # This is ignored comment
      DATABASE_URL=mysql2://user:psw@0.0.0:3307/database
      RACK_ENV=development
      

      (基于@user664833的解决方案)

      【讨论】:

        【解决方案8】:

        在您的 Gemfile 中添加 gem 'dotenv-rails' 运行命令bundle install 在根目录中添加 .env 文件并编写环境变量,如

        export RAILS_ENV=production && rails c
        

        导出 AUTH="xyz 891f5089ba563cd1ea55b73467"

        从应用程序中的任何地方调用环境,也可以在 Rails 控制台中调用 运行rails consoleENV['AUTH'] 然后回车,你会发现你的结果xyz 891f5089ba563cd1ea55b73467

        【讨论】:

          猜你喜欢
          • 2011-06-25
          • 1970-01-01
          • 2013-07-09
          • 1970-01-01
          • 2018-09-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-08-21
          相关资源
          最近更新 更多