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

时间:2011-02-06 04:35:16

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

我知道我可以通过

在bash中设置我的ENV变量
export admin_password = "secret"

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

中是这样的
ENV['admin_password'] = "secret"

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

8 个答案:

答案 0 :(得分:123)

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.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', '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 production ,因为您永远不会将此文件提交到源代码管理系统中,因此它默认用于开发上下文。但是,如果您需要为 test 环境设置一些特殊内容(或者在本地测试生产模式 的情况下),只需添加一个条件块以下所有其他变量:

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内,您必须将布尔数字指定为字符串(例如ENV['SEND_MAIL'] = 'false'而不仅仅是false {1}}和ENV['TIMEOUT'] = '30'不只是30),否则您将分别收到错误can't convert false into Stringcan't convert Fixnum into String

存储和共享敏感信息

最后的结点是:如何与您的客户和/或合作伙伴分享这些敏感信息?出于业务连续性的目的(即当您遇到一颗流星时,将如何您的客户和/或合作伙伴恢复网站的全部运营?),您的客户和/或合作伙伴需要知道您的应用所需的所有凭据。通过电子邮件发送/浏览这些东西是不安全的,会导致混乱。将它存储在共享的Google文档中并不坏(如果每个人都使用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

Foreman和.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;那些对不会成为那里的变量然后,所以你不能引用已经设置的变量(保持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']

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

答案 1 :(得分:75)

<强> [更新]

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

您应该能够像在问题中指定的那样设置环境变量。例如,我有一个使用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标记。)

答案 2 :(得分:10)

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

# environment/development.rb

ENV['admin_password'] = "secret" 

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

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

答案 3 :(得分:8)

除了这里的解决方案之外,如果您使用某些开发服务器,还有更清晰的选择。

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

ADMIN_PASSOWRD="secret"

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

export ADMIN_PASSOWRD="secret"

答案 4 :(得分:2)

我认为最好的方法是将它们存储在某个yml文件中,然后在intializer文件中使用此命令加载该文件

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'

答案 5 :(得分:1)

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

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

答案 6 :(得分:1)

加载自定义.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的解决方案)

答案 7 :(得分:0)

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

export RAILS_ENV=production && rails c

导出 AUTH="xyz 891f5089ba563cd1ea55b73467"

从应用程序中的任何地方调用 env 也是你的导轨控制台 运行rails consoleENV['AUTH'] 然后按回车,你会发现你的结果xyz 891f5089ba563cd1ea55b73467