Объясните использование переменных окружения.ruby-93

Переменные окружения (environment variables) — важный механизм для настройки приложений и передачи параметров в runtime. Рассмотрим их использование в Ruby-приложениях.

1. Основы работы с переменными окружения

Получение значений

# Базовый способ
db_host = ENV['DB_HOST']

# С значением по умолчанию
db_port = ENV.fetch('DB_PORT', '5432')

# Проверка наличия
unless ENV.key?('API_KEY')
  raise "Не задан API_KEY в переменных окружения"
end

Установка значений

ENV['TMP_DIR'] = '/tmp/custom'
puts ENV['TMP_DIR'] # => "/tmp/custom"

2. Практические примеры использования

Конфигурация базы данных

ActiveRecord::Base.establish_connection(
  adapter:  ENV.fetch('DB_ADAPTER', 'postgresql'),
  host:     ENV['DB_HOST'],
  database: ENV['DB_NAME'],
  username: ENV['DB_USER'],
  password: ENV['DB_PASSWORD'],
  port:     ENV.fetch('DB_PORT', '5432')
)

Настройки приложения

class AppConfig
  def self.max_upload_size
    ENV.fetch('MAX_UPLOAD_SIZE', '100').to_i * 1024 * 1024
  end

  def self.debug_mode?
    ENV['DEBUG'] == 'true'
  end
end

3. Безопасная работа с переменными окружения

Валидация значений

def get_required_env(var_name)
  ENV.fetch(var_name) do
    raise ArgumentError, "Необходимо задать #{var_name} в переменных окружения"
  end
end

api_key = get_required_env('API_KEY')

Чувствительные данные

# Никогда не логируйте секретные данные!
logger.info("Using API key: #{ENV['API_KEY']}") # ПЛОХО
logger.info("Using API key: [FILTERED]")       # ХОРОШО

4. Загрузка переменных из файлов

Использование dotenv

# Установите gem 'dotenv-rails' для Rails или 'dotenv' для других проектов
require 'dotenv'
Dotenv.load('.env.local', '.env') # Загружает файлы по порядку

# Теперь переменные доступны в ENV
puts ENV['SECRET_KEY']

Формат .env файла:

DB_HOST=localhost
DB_USER=app_user
DB_PASS=s3cr3t

5. Особенности в разных средах

Разделение конфигов по средам

# config/environments/production.env
REDIS_URL=redis://prod.example.com:6379/1

# config/environments/development.env
REDIS_URL=redis://localhost:6379/1

Использование в Docker

Dockerfile пример:

FROM ruby:3.2
ENV RAILS_ENV=production
COPY . /app
CMD ["rails", "server"]

Запуск с переменными:

docker run -e "DB_HOST=db.example.com" my_app

6. Паттерны для работы с ENV

Обертка для доступа к переменным

module AppEnv
  module_function

  def database_url
    ENV.fetch('DATABASE_URL') do
      "#{ENV['DB_ADAPTER']}://#{ENV['DB_USER']}:#{ENV['DB_PASSWORD']}@#{ENV['DB_HOST']}/#{ENV['DB_NAME']}"
    end
  end

  def production?
    ENV['RACK_ENV'] == 'production' || ENV['RAILS_ENV'] == 'production'
  end
end

Типизированный доступ

module EnvParser
  module_function

  def string(key, default = nil)
    ENV.fetch(key, default)
  end

  def integer(key, default = 0)
    ENV[key]&.to_i || default
  end

  def boolean(key, default = false)
    val = ENV[key]
    val.nil? ? default : val.downcase == 'true'
  end
end

7. Лучшие практики

  1. Не коммитьте .env файлы в git, добавьте их в .gitignore
  2. Используйте .env.example как шаблон для настроек
  3. Не используйте ENV напрямую в бизнес-логике, выносите в конфиги
  4. Документируйте необходимые переменные в README
  5. Разделяйте переменные по средам (development, test, production)
  6. Используйте секреты (Vault, AWS Secrets Manager) для production

Резюмируем

Переменные окружения в Ruby предоставляют гибкий механизм конфигурации:

  • Доступ через глобальный хэш ENV
  • Лучше использовать fetch со значениями по умолчанию
  • Для удобства разработки используйте dotenv
  • Всегда проверяйте наличие обязательных переменных
  • Не храните секреты в коде - только в переменных окружения
  • Для сложных проектов создавайте обертки над ENV

Правильное использование переменных окружения делает приложения более:

  • Безопасными (секреты не в коде)
  • Портативными (разные среды без изменений кода)
  • Масштабируемыми (разные конфиги для разных инстансов)