Ruby-on-rails 是否可以在我的代码中为 rails 开发环境设置 ENV 变量?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4911607/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is it possible to set ENV variables for rails development environment in my code?
提问by Lan
I know that I can set my ENV variables in bash via
我知道我可以通过在 bash 中设置我的 ENV 变量
export admin_password = "secret"
But is there a way to do it in my rails source code somewhere? My first attempt was something like this in environment/development.rb
但是有没有办法在我的 rails 源代码中的某个地方做到这一点?我的第一次尝试是这样的environment/development.rb
ENV['admin_password'] = "secret"
But it didn't work. Is there a way to do this?
但它没有用。有没有办法做到这一点?
采纳答案by Michelle Tilley
[Update]
[更新]
While the solution under "old answer" will work for general problems, this section is to answer your specific question after clarification from your comment.
虽然“旧答案”下的解决方案适用于一般问题,但本节将在您的评论澄清后回答您的具体问题。
You should be able to set environment variables exactly like you specify in your question. As an example, I have a Heroku app that uses HTTP basic authentication.
您应该能够完全按照您在问题中指定的方式设置环境变量。例如,我有一个使用 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
So in your case you would use
所以在你的情况下你会使用
unless Rails.env.production?
ENV['admin_password'] = "secret"
end
Don't forget to restart the server so the configuration is reloaded!
不要忘记重新启动服务器,以便重新加载配置!
[Old Answer]
[旧答案]
For app-wide configuration, you might consider a solution like the following:
对于应用程序范围的配置,您可能会考虑如下解决方案:
Create a file config/application.ymlwith a hash of options you want to be able to access:
创建一个包含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
Now, create the file config/initializers/app_config.rband include the following:
现在,创建文件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)
Now, anywhere in your application, you can access APP_CONFIG[:admin_password], along with all your other data. (Note that since the initializer includes ERB.new, your YAML file can contain ERB markup.)
现在,您可以在应用程序的任何位置访问APP_CONFIG[:admin_password]以及所有其他数据。(请注意,由于初始化程序包含ERB.new,您的 YAML 文件可以包含 ERB 标记。)
回答by user664833
Never hardcode sensitive information (account credentials, passwords, etc.). Instead, create a file to store that information as environment variables (key/value pairs), and exclude that file from your source code management system. For example, in terms of Git (source code management system), exclude that file by adding it to .gitignore:
切勿对敏感信息(帐户凭据、密码等)进行硬编码。相反,创建一个文件来将该信息存储为环境变量(键/值对),并从源代码管理系统中排除该文件。例如,就 Git(源代码管理系统)而言,通过将该文件添加到 . gitignore:
-bash> echo '/config/app_environment_variables.rb' >> .gitignore
/config/app_environment_variables.rb
/config/app_environment_variables.rb
ENV['HTTP_USER'] = 'devuser'
ENV['HTTP_PASS'] = 'devpass'
As well, add the following lines to /config/environment.rb, between the requireline, and the Application.initializeline:
同样,将以下几行添加到/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)
That's it!
就是这样!
As the comment above says, by doing this you will be loading your environment variables before environments/*.rb, which means that you will be able to refer to your variables inside those files (e.g. environments/production.rb). This is a great advantage over putting your environment variables file inside /config/initializers/.
正如上面的评论所说,通过这样做,您将在 之前加载您的环境变量environments/*.rb,这意味着您将能够在这些文件(例如environments/production.rb)中引用您的变量。与将环境变量文件放在/config/initializers/.
Inside app_environment_variables.rbthere's no need to distinguish environments as far as developmentor productionbecause you will never commit this file into your source code management system, hence it is for the developmentcontext by default. But if you need to set something special for the testenvironment (or for occasions when you test productionmode locally), just add a conditional block belowall the other variables:
在内部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
Whenever you update app_environment_variables.rb, restart the app server. Assuming you are using the likes of Apache/Passenger or rails server:
每当您更新时app_environment_variables.rb,请重新启动应用服务器。假设您使用的是 Apache/Passenger 或rails server:
-bash> touch tmp/restart.txt
In your code, refer to the environment variables as follows:
在您的代码中,参考环境变量如下:
def authenticate
authenticate_or_request_with_http_basic do |username, password|
username == ENV['HTTP_USER'] && password == ENV['HTTP_PASS']
end
end
Note that inside app_environment_variables.rbyou must specify booleansand numbersas strings(e.g. ENV['SEND_MAIL'] = 'false'not just false, and ENV['TIMEOUT'] = '30'not just 30), otherwise you will get the errors can't convert false into Stringand can't convert Fixnum into String, respectively.
请注意,在内部,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。
Storing and sharing sensitive information
存储和共享敏感信息
The final knot to tie is: how to share this sensitive information with your clients and/or partners?For the purpose of business continuity (i.e. when you get hit by a falling star, how will your clients and/or partners resume full operations of the site?), your clients and/or partners need to know all the credentials required by your app. Emailing/Skyping these things around is insecure and leads to disarray. Storing it in shared Google Docs is not bad (if everyone uses https), but an app dedicated to storing and sharing small titbits like passwords would be ideal.
最后要解决的问题是:如何与您的客户和/或合作伙伴分享这些敏感信息?出于业务连续性的目的(即当您遇到一颗流星时,您的客户和/或合作伙伴将如何恢复网站的全面运营?),您的客户和/或合作伙伴需要了解您的应用程序所需的所有凭据. 通过电子邮件/ Skyping 这些东西是不安全的,会导致混乱。将它存储在共享的 Google Docs 中并不错(如果每个人都使用 https),但是一个专门用于存储和共享密码等小花絮的应用程序将是理想的选择。
How to set environment variables on Heroku
如何在 Heroku 上设置环境变量
If you have a single environment on Heroku:
如果您在 Heroku 上只有一个环境:
-bash> heroku config:add HTTP_USER='herouser'
-bash> heroku config:add HTTP_USER='heropass'
If you have multiple environmentson Heroku:
如果您在 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
Foreman and .env
工头和 .env
Many developers use Foreman(installed with the Heroku Toolbelt) to run their apps locally(as opposed to using the likes of Apache/Passenger or rails server). Foreman and Heroku use Procfilefor declaring what commands are run by your application, so the transition from local dev to Heroku is seamless in that regard. I use Foreman and Heroku in every Rails project, so this convenience is great. But here's the thing.. Foreman loads environment variables stored in /.envvia dotenvbut unfortunately dotenv essentially only parses the file for key=valuepairs; those pairs don't become variables right there and then, so you can't refer to already set variables (to keep things DRY), nor can you do "Ruby" in there (as noted above with the conditionals), which you can do in /config/app_environment_variables.rb. For instance, in terms of keeping things DRY I sometimes do stuff like this:
许多开发人员使用 Foreman(与Heroku Toolbelt一起安装)在本地运行他们的应用程序(而不是使用 Apache/Passenger 或 之类的工具rails server)。Foreman 和 HerokuProcfile用于声明您的应用程序运行哪些命令,因此从本地开发人员到 Heroku 的过渡在这方面是无缝的。我在每个 Rails 项目中都使用 Foreman 和 Heroku,所以这种便利性非常好。但事情就是这样.. Foreman/.env通过 dotenv加载存储的环境变量,但不幸的是dotenv 基本上只解析文件key=value对; 这些对不会立即成为变量,因此您不能引用已经设置的变量(以保持 DRY),也不能在其中执行“Ruby”(如上面的条件语句所述),您可以做在/config/app_environment_variables.rb。例如,在保持干燥方面,我有时会做这样的事情:
ENV['SUPPORT_EMAIL']='Company Support <[email protected]>'
ENV['MAILER_DEFAULT_FROM'] = ENV['SUPPORT_EMAIL']
ENV['MAILER_DEFAULT_TO'] = ENV['SUPPORT_EMAIL']
Hence, I use Foreman to run my apps locally, but I don't use its .envfile for loading environment variables; rather I use Foreman in conjunction with the /config/app_environment_variables.rbapproach described above.
因此,我使用 Foreman 在本地运行我的应用程序,但我不使用它的.env文件来加载环境变量;相反,我将 Foreman 与上述/config/app_environment_variables.rb方法结合使用。
回答by Lan
The way I am trying to do this in my question actually works!
我在我的问题中尝试这样做的方式实际上有效!
# environment/development.rb
ENV['admin_password'] = "secret"
I just had to restart the server. I thought running reload!in rails console would be enough but I also had to restart the web server.
我只需要重新启动服务器。我认为reload!在 rails 控制台中运行就足够了,但我还必须重新启动 Web 服务器。
I am picking my own answer because I feel this is a better place to put and set the ENV variables
我正在选择我自己的答案,因为我觉得这是放置和设置 ENV 变量的更好地方
回答by Aupajo
As an aside to the solutions here, there are cleaner alternatives if you're using certain development servers.
除了这里的解决方案,如果您使用某些开发服务器,还有更清洁的替代方案。
With Heroku's Foreman, you can create per-project environment variables in a .envfile:
使用 Heroku 的Foreman,您可以在.env文件中创建每个项目的环境变量:
ADMIN_PASSOWRD="secret"
With Pow, you can use a .powenvfile:
使用Pow,您可以使用.powenv文件:
export ADMIN_PASSOWRD="secret"
回答by Taimoor Changaiz
I think the best way is to store them in some yml file and then load that file using this command in intializer file
我认为最好的方法是将它们存储在某个 yml 文件中,然后在初始化文件中使用此命令加载该文件
APP_CONFIG = YAML.load_file("#{Rails.root}/config/CONFIG.yml")[Rails.env].to_hash
you can easily access environment related config variables.
您可以轻松访问与环境相关的配置变量。
Your Yml file key value structure:
您的 Yml 文件键值结构:
development:
app_key: 'abc'
app_secret: 'abc'
production:
app_key: 'xyz'
app_secret: 'ghq'
回答by Daniel Garmoshka
Script for loading of custom .envfile:
Add the following lines to /config/environment.rb, between the requireline, and the Application.initializeline:
用于加载自定义.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
And config/local_environment.env(you will want to .gitignoreit) will look like:
并且config/local_environment.env(你会想要.gitignore它)看起来像:
# This is ignored comment
DATABASE_URL=mysql2://user:[email protected]:3307/database
RACK_ENV=development
(Based on solution of @user664833)
(基于@user664833的解决方案)
回答by goncalossilva
The system environment and rails' environment are different things. ENVlet's you work with the rails' environment, but if what you want to do is to change the system's environment in runtime you can just surround the command with backticks.
系统环境和 rails 的环境是不同的东西。ENV让我们使用 rails 的环境,但是如果您想要在运行时更改系统环境,您可以只用反引号将命令括起来。
# ruby code
`export admin_password="secret"`
# more ruby code

