是否有可能在我的代码中为rails开发环境设置ENVvariables?
我知道我可以通过bash设置我的ENVvariables
export admin_password = "secret"
但有没有办法在我的rails源代码中执行它? 我的第一次尝试是在这样的environment/development.rb
ENV['admin_password'] = "secret"
但它没有工作。 有没有办法做到这一点?
[更新]
虽然“旧答案”下的解决scheme适用于一般问题,但本部分将在您的评论澄清后回答您的具体问题。
你应该可以像你在问题中指定的一样设置环境variables。 作为一个例子,我有一个使用HTTP基本authentication的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
不要忘记重新启动服务器,以便重新加载configuration!
[老问答]
对于应用程序范围的configuration,您可以考虑如下的解决scheme:
创build一个文件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
现在,创build文件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标记。)
不要硬编码敏感信息(帐户凭证,密码等) 。 相反,创build一个文件来存储这些信息作为环境variables(键/值对),并从源代码pipe理系统中排除该文件。 例如,就Git(源代码pipe理系统)而言,通过添加它来排除该文件。 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
下行添加到/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
之前加载您的环境variables,这意味着您将能够在这些文件内引用您的variables(例如environments/production.rb
)。 把你的环境variables文件放在/config/initializers/
里面是一个很大的优势。
在app_environment_variables.rb
里面,不需要区分开发环境和生产环境,因为你永远不会把这个文件提交到你的源代码pipe理系统,因此默认情况下是用于开发环境。 但是如果你需要为testing环境设置一些特殊的东西(或者在本地testing生产模式的场合),只需要在所有其他variables下添加一个条件块:
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
在你的代码中,参考如下的环境variables:
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
您必须指定布尔值和数字作为string (例如ENV['SEND_MAIL'] = 'false'
不只是false
,而ENV['TIMEOUT'] = '30'
ENV['SEND_MAIL'] = 'false'
ENV['TIMEOUT'] = '30'
不只是30
),否则您将获得错误can't convert false into String
, can't convert Fixnum into String
。
存储和共享敏感信息
最后的结局是: 如何与客户和/或合作伙伴分享这些敏感信息? 为了实现业务连续性(例如,当您受到meteor影响,您的客户和/或合作伙伴如何恢复网站的全面运营?),您的客户和/或合作伙伴需要知道您的应用所需的所有凭据。 通过电子邮件发送/将这些事情拖到空中是不安全的,并导致混乱。 将其存储在共享的Google文档中并不差(如果每个人都使用https),但专门用于存储和共享密码等应用程序的应用程序将是理想select。
如何在Heroku上设置环境variables
如果你在Heroku上有一个单一的环境:
-bash> heroku config:add HTTP_USER='herouser' -bash> heroku config:add HTTP_USER='heropass'
如果你在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
工头和.env
许多开发人员使用Foreman (与Heroku Toolbelt一起安装)在本地运行应用程序 (而不是使用Apache / Passenger或rails server
)。 Foreman和Heroku使用Procfile
来声明你的应用程序运行了什么命令 ,所以从本地开发到Heroku的过渡在这方面是无缝的。 我在每个Rails项目中都使用Foreman和Heroku,所以这个方便性非常好。 但是这里的东西.. 工头加载通过dotenv存储在/.env
环境variables,但不幸的是dotenv本质上只parsing文件的key=value
对 ; 那些对在这里不会变成variables,所以你不能引用已经设置好的variables(保持干燥),也不能在那里做“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
文件来加载环境variables; 相反,我将Foreman与上述的/config/app_environment_variables.rb
方法结合使用。
除了这里的解决scheme外,如果您使用某些开发服务器,还有更清晰的替代scheme。
使用Heroku的工头 ,您可以在.env
文件中创build每个项目的环境variables:
ADMIN_PASSOWRD="secret"
使用Pow ,你可以使用.powenv
文件:
export ADMIN_PASSOWRD="secret"
我试图在我的问题中这样做的方式实际上是有效的!
# environment/development.rb ENV['admin_password'] = "secret"
我只需要重新启动服务器。 我想运行reload!
在轨道控制台将是足够的,但我也不得不重新启动Web服务器。
我select自己的答案,因为我觉得这是一个更好的地方放置和设置ENVvariables
我认为最好的方法是将它们存储在某个yml文件中,然后使用intializer文件中的该命令加载该文件
APP_CONFIG = YAML.load_file("#{Rails.root}/config/CONFIG.yml")[Rails.env].to_hash
您可以轻松访问环境相关的configurationvariables。
你的Yml文件键值结构:
development: app_key: 'abc' app_secret: 'abc' production: app_key: 'xyz' app_secret: 'ghq'
系统环境和rails的环境是不同的东西。 ENV
让你使用rails的环境,但是如果你想要做的是在运行时改变系统的环境,你可以用反引号包围命令。
# ruby code `export admin_password="secret"` # more ruby code
加载自定义.env
文件的脚本: .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的解决scheme)