Можно ли установить переменные ENV для среды разработки рельсов в моем коде? - PullRequest
77 голосов
/ 06 февраля 2011

Я знаю, что могу установить свои переменные ENV в bash с помощью

export admin_password = "secret"

Но есть ли способ сделать это в моем исходном коде rails? Моя первая попытка была примерно такой в ​​environment/development.rb

ENV['admin_password'] = "secret"

Но это не сработало. Есть ли способ сделать это?

Ответы [ 7 ]

124 голосов
/ 01 августа 2012

Никогда не кодируйте конфиденциальную информацию (учетные данные, пароли и т. Д.) . Вместо этого создайте файл для хранения этой информации в виде переменных среды (пары ключ / значение) и исключите этот файл из системы управления исходным кодом. Например, с точки зрения Git (системы управления исходным кодом), исключите этот файл, добавив его в. gitignore :

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

/ конфигурации / 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 (или для случаев, когда вы тестируете production mode local ), просто добавьте условный блок ниже все остальные переменные:

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, а 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'

Если у вас несколько сред на 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). Форман и Heroku используют Procfile для объявления того, какие команды выполняются вашим приложением , поэтому переход от локального разработчика к Heroku в этом отношении беспроблемен. Я использую Foreman и Heroku в каждом проекте Rails, поэтому это удобство очень велико. Но вот в чем дело ... Форман загружает переменные окружения, хранящиеся в /.env, через dotenv , но, к сожалению, dotenv, по сути, анализирует файл только для key=value пар ; эти пары не становятся переменными тут же и тогда, поэтому вы не можете ссылаться на уже установленные переменные (чтобы сохранить вещи СУХИМЫМИ), и вы не можете делать там «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, описанным выше.

76 голосов
/ 06 февраля 2011

[Update]

Хотя решение в разделе «старый ответ» будет работать для общих проблем, этот раздел предназначен для ответа на ваш конкретный вопрос после уточнения вашего комментария.

Вы должны иметь возможность устанавливать переменные окружения точно так, как вы указали в своем вопросе. Например, у меня есть приложение Heroku, которое использует базовую аутентификацию HTTP.

# 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.)

10 голосов
/ 07 февраля 2011

Способ, которым я пытаюсь сделать это в моем вопросе, на самом деле работает!

# environment/development.rb

ENV['admin_password'] = "secret" 

Мне просто нужно было перезагрузить сервер.Я подумал, что достаточно запустить reload! в консоли rails, но мне также пришлось перезапустить веб-сервер.

Я выбираю свой собственный ответ, потому что считаю, что это лучшее место для установки и установки переменных ENV

8 голосов
/ 06 августа 2012

В дополнение к решениям здесь, есть более чистые альтернативы, если вы используете определенные серверы разработки.

С Heroku Foreman вы можете создавать переменные среды для проекта в файле .env:

ADMIN_PASSOWRD="secret"

С Pow , вы можете использовать .powenv файл:

export ADMIN_PASSOWRD="secret"
2 голосов
/ 06 мая 2013

Я думаю, что лучший способ - сохранить их в каком-то файле 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'
1 голос
/ 21 июля 2016

Скрипт для загрузки пользовательского файла .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)

1 голос
/ 06 февраля 2011

Системная среда и среда рельсов - это разные вещи. ENV давайте поработаем со средой rails, но если вы хотите изменить среду системы во время выполнения, вы можете просто окружить команду обратными чертами.

# ruby code
`export admin_password="secret"`
# more ruby code
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...