是否可以在我的代码中为rails开发环境设置ENV变量?

Lan*_*Lan 79 ruby-on-rails ruby-on-rails-3

我知道我可以在bash中设置我的ENV变量

export admin_password = "secret"
Run Code Online (Sandbox Code Playgroud)

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

ENV['admin_password'] = "secret"
Run Code Online (Sandbox Code Playgroud)

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

use*_*833 125

切勿对敏感信息(帐户凭据,密码等)进行硬编码.而是创建一个文件以将该信息存储为环境变量(键/值对),并从源代码管理系统中排除该文件.例如,就Git(源代码管理系统)而言,通过将其添加到该文件中来排除该文件.gitignore:

-bash> echo '/config/app_environment_variables.rb' >> .gitignore 
Run Code Online (Sandbox Code Playgroud)

/config/app_environment_variables.rb

ENV['HTTP_USER'] = 'devuser'
ENV['HTTP_PASS'] = 'devpass'
Run Code Online (Sandbox Code Playgroud)

同样,在行和行/config/environment.rb之间添加以下行:requireApplication.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)
Run Code Online (Sandbox Code Playgroud)

而已!

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

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

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
Run Code Online (Sandbox Code Playgroud)

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

-bash> touch tmp/restart.txt
Run Code Online (Sandbox Code Playgroud)

在您的代码中,请按如下方式引用环境变量:

def authenticate
  authenticate_or_request_with_http_basic do |username, password|
    username == ENV['HTTP_USER'] && password == ENV['HTTP_PASS']
  end
end
Run Code Online (Sandbox Code Playgroud)

请注意,在内部,app_environment_variables.rb您必须将布尔值数字指定为字符串(例如,ENV['SEND_MAIL'] = 'false'不仅仅是false,而ENV['TIMEOUT'] = '30'不仅仅是30),否则您将分别得到错误can't convert false into String和错误can't convert Fixnum into String.

存储和共享敏感信息

最后的结点是:如何与您的客户和/或合作伙伴分享这些敏感信息?出于业务连续性的目的(即当您遭遇堕落之星,您的客户和/或合作伙伴将如何恢复该网站的全部运营?),您的客户和/或合作伙伴需要知道您的应用所需的所有凭据.通过电子邮件发送/浏览这些东西是不安全的,会导致混乱.将它存储在共享的Google文档中并不错(如果每个人都使用https),但是专门用于存储和共享小密码(如密码)的应用程序将是理想的选择.

如何在Heroku上设置环境变量

如果你在Heroku上有一个环境:

-bash> heroku config:add HTTP_USER='herouser'
-bash> heroku config:add HTTP_USER='heropass'
Run Code Online (Sandbox Code Playgroud)

如果Heroku上有多个环境:

-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
Run Code Online (Sandbox Code Playgroud)

工头和.env

许多开发人员使用Foreman(与Heroku Toolbelt一起安装)在本地运行他们的应用程序(而不是使用Apache/Passenger等rails server).Foreman和Heroku Procfile用于声明应用程序运行的命令,因此从本地开发到Heroku的转换在这方面是无缝的.我在每个Rails项目中使用Foreman和Heroku,因此这种方便性非常好.但这就是事情.. Foreman加载存储在/.envvia dotenv中的环境变量,但遗憾的是dotenv基本上只解析文件中的key=value ; 那些对不会成为那里的变量然后,所以你不能引用已经设置的变量(保持DRY),也不能在那里做"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']
Run Code Online (Sandbox Code Playgroud)

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

  • 我喜欢这个解决方案,因为我想确保敏感设置(API密钥等)在密钥库中得到充分保护,而不是以明文形式保护,而不是与Git存储库捆绑在一起.谢谢. (3认同)

Mic*_*ley 77

[更新]

虽然"旧答案"下的解决方案适用于一般问题,但本节将在您的评论澄清之后回答您的具体问题.

您应该能够像在问题中指定的那样设置环境变量.例如,我有一个使用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
Run Code Online (Sandbox Code Playgroud)

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

unless Rails.env.production?
  ENV['admin_password'] = "secret"
end
Run Code Online (Sandbox Code Playgroud)

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

[旧答案]

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

创建一个文件,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
Run Code Online (Sandbox Code Playgroud)

现在,创建文件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)
Run Code Online (Sandbox Code Playgroud)

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

  • 好吧,我正在使用Heroku,它们允许你设置一些ENV变量,用于你不想检查源代码控制的密码.我正在试图找出我的开发机器上最好的事情.是的,我正在尝试使用我的应用程序中的数据. (2认同)

Lan*_*Lan 10

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

# environment/development.rb

ENV['admin_password'] = "secret" 
Run Code Online (Sandbox Code Playgroud)

我只需要重启服务器.我认为reload!在rails console中运行就足够了,但我还必须重新启动Web服务器.

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


Aup*_*ajo 8

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

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

ADMIN_PASSOWRD="secret"
Run Code Online (Sandbox Code Playgroud)

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

export ADMIN_PASSOWRD="secret"
Run Code Online (Sandbox Code Playgroud)