Ruby Environment Variables
Environment variables are dynamic values defined in the operating system that can affect how programs run. Ruby provides multiple ways to access and manipulate environment variables. This chapter will explain in detail how to use environment variables in Ruby.
🌍 What are Environment Variables?
Environment variables are operating system-level configuration parameters that provide configuration information for programs running on the system. Common environment variables include:
- PATH: Search path for executable files
- HOME: User home directory
- USER: Current username
- LANG: System language setting
- RUBY_ENV: Ruby application environment (development, production, test)
📦 Accessing Environment Variables
Using the ENV Object
Ruby accesses environment variables through the built-in ENV object, which is a hash-like object:
ruby
# Get environment variables
home_dir = ENV['HOME']
user_name = ENV['USER']
path = ENV['PATH']
puts "Home directory: #{home_dir}"
puts "Username: #{user_name}"
puts "Path: #{path}"
# Check if environment variable exists
if ENV.has_key?('RUBY_ENV')
puts "Ruby environment: #{ENV['RUBY_ENV']}"
else
puts "RUBY_ENV environment variable not set"
end
# Get all environment variables
puts "All environment variables:"
ENV.each do |key, value|
puts "#{key}: #{value}"
endSafe Access to Environment Variables
ruby
# Provide default values
database_url = ENV.fetch('DATABASE_URL', 'sqlite://localhost/default.db')
api_key = ENV.fetch('API_KEY') { 'default-api-key' }
# Check if it exists
if ENV.key?('SECRET_KEY')
secret_key = ENV['SECRET_KEY']
else
puts "Warning: SECRET_KEY environment variable not set"
secret_key = 'default-secret'
end
# Using ternary operator
debug_mode = ENV['DEBUG'] ? ENV['DEBUG'] == 'true' : false🛠️ Setting Environment Variables
Setting in Ruby Program
ruby
# Set environment variables
ENV['MY_APP_NAME'] = 'My Ruby Application'
ENV['APP_VERSION'] = '1.0.0'
# Verify settings
puts "Application name: #{ENV['MY_APP_NAME']}"
puts "Application version: #{ENV['APP_VERSION']}"
# Delete environment variable
ENV.delete('MY_APP_NAME')
puts "Application name: #{ENV['MY_APP_NAME']}" # nilSetting in Different Operating Systems
Linux/macOS Systems
bash
# Temporary setting (valid for current session)
export DATABASE_URL="postgresql://localhost/myapp"
export API_KEY="your-api-key-here"
# Setting in shell script
#!/bin/bash
export RUBY_ENV=production
ruby my_app.rb
# Permanent setting in .bashrc or .zshrc
echo 'export RUBY_ENV=development' >> ~/.bashrc
source ~/.bashrcWindows Systems
cmd
# Command line setting (valid for current session)
set DATABASE_URL=postgresql://localhost/myapp
set API_KEY=your-api-key-here
# PowerShell setting
$env:RUBY_ENV="production"
# Permanent setting (system environment variables)
# Set through System Properties -> Advanced -> Environment Variables🎯 Common Ruby Environment Variables
Ruby-Related Environment Variables
ruby
# RUBY_ENV - Application environment
ruby_env = ENV.fetch('RUBY_ENV', 'development')
case ruby_env
when 'development'
puts "Development environment mode"
when 'production'
puts "Production environment mode"
when 'test'
puts "Test environment mode"
else
puts "Unknown environment: #{ruby_env}"
end
# RUBYLIB - Ruby library path
ruby_lib_path = ENV['RUBYLIB']
puts "Ruby library path: #{ruby_lib_path}" if ruby_lib_path
# RUBYOPT - Ruby command line options
ruby_options = ENV['RUBYOPT']
puts "Ruby options: #{ruby_options}" if ruby_options
# GEM_PATH - Gem search path
gem_path = ENV['GEM_PATH']
puts "Gem path: #{gem_path}" if gem_path
# GEM_HOME - Gem installation directory
gem_home = ENV['GEM_HOME']
puts "Gem home directory: #{gem_home}" if gem_homeApplication Environment Variables
ruby
# Database configuration
database_url = ENV.fetch('DATABASE_URL') do
case ENV.fetch('RUBY_ENV', 'development')
when 'development'
'sqlite://localhost/development.db'
when 'test'
'sqlite://localhost/test.db'
when 'production'
raise "DATABASE_URL environment variable must be set"
end
end
# API key
api_key = ENV.fetch('API_KEY') do
puts "Warning: Using default API key (development only)"
'default-api-key'
end
# Server configuration
server_port = ENV.fetch('PORT', 3000).to_i
server_host = ENV.fetch('HOST', 'localhost')
puts "Server configuration: #{server_host}:#{server_port}"🛡️ Environment Variable Security
Sensitive Information Handling
ruby
class Config
# Sensitive environment variable list
SENSITIVE_VARS = %w[
DATABASE_URL
API_KEY
SECRET_KEY
PASSWORD
PRIVATE_KEY
].freeze
def self.get(key, default = nil)
value = ENV[key]
return default if value.nil? || value.empty?
value
end
def self.get_required(key)
value = ENV[key]
raise "Environment variable must be set: #{key}" if value.nil? || value.empty?
value
end
def self.safe_display
ENV.each do |key, value|
if SENSITIVE_VARS.any? { |sensitive| key.upcase.include?(sensitive) }
puts "#{key}: ********" # Hide sensitive information
else
puts "#{key}: #{value}"
end
end
end
end
# Usage example
begin
db_url = Config.get_required('DATABASE_URL')
api_key = Config.get('API_KEY', 'default-key')
puts "Configuration loaded successfully"
rescue => e
puts "Configuration error: #{e.message}"
endEnvironment Variable Validation
ruby
class EnvironmentValidator
def self.validate_required(vars)
missing = []
vars.each do |var|
missing << var unless ENV[var] && !ENV[var].empty?
end
unless missing.empty?
raise "Missing required environment variables: #{missing.join(', ')}"
end
end
def self.validate_format(var, pattern, description = nil)
value = ENV[var]
return true if value.nil? || value.empty?
unless value.match?(pattern)
desc = description || "#{var} format is incorrect"
raise "Environment variable validation failed: #{desc}"
end
true
end
def self.validate_numeric(var, min = nil, max = nil)
value = ENV[var]
return true if value.nil? || value.empty?
begin
num = Integer(value)
if min && num < min
raise "Environment variable #{var} must be greater than or equal to #{min}"
end
if max && num > max
raise "Environment variable #{var} must be less than or equal to #{max}"
end
rescue ArgumentError
raise "Environment variable #{var} must be a number"
end
true
end
end
# Usage example
begin
# Validate required environment variables
EnvironmentValidator.validate_required(['DATABASE_URL', 'API_KEY'])
# Validate email format
EnvironmentValidator.validate_format('ADMIN_EMAIL',
/\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i,
'Admin email format is incorrect')
# Validate port number
EnvironmentValidator.validate_numeric('PORT', 1, 65535)
puts "Environment variable validation passed"
rescue => e
puts "Environment variable validation failed: #{e.message}"
exit 1
end📁 Environment Configuration Management
Using Configuration Files
ruby
require 'yaml'
class EnvironmentConfig
def self.load_config(config_file = 'config.yml')
# Load configuration file
config = YAML.load_file(config_file) rescue {}
# Merge environment variables
env = ENV.fetch('RUBY_ENV', 'development')
config.merge(config[env] || {})
end
def self.database_config
{
url: ENV.fetch('DATABASE_URL') { default_database_url },
pool: ENV.fetch('DB_POOL_SIZE', 5).to_i,
timeout: ENV.fetch('DB_TIMEOUT', 5000).to_i
}
end
private
def self.default_database_url
case ENV.fetch('RUBY_ENV', 'development')
when 'development'
'sqlite://localhost/development.db'
when 'test'
'sqlite://localhost/test.db'
when 'production'
raise "DATABASE_URL must be set in production environment"
end
end
end
# config.yml example
=begin
---
development:
database_url: sqlite://localhost/dev.db
api_key: dev-key
debug: true
production:
debug: false
test:
database_url: sqlite://localhost/test.db
api_key: test-key
=end
# Using configuration
config = EnvironmentConfig.load_config
puts "Database URL: #{config['database_url']}"Environment-Specific Configuration
ruby
class AppConfig
def self.environment
@environment ||= ENV.fetch('RUBY_ENV', 'development')
end
def self.development?
environment == 'development'
end
def self.production?
environment == 'production'
end
def self.test?
environment == 'test'
end
def self.log_level
if development?
'debug'
elsif production?
'warn'
else
'info'
end
end
def self.cache_enabled?
return false if development?
ENV.fetch('CACHE_ENABLED', 'true') == 'true'
end
def self.worker_processes
if production?
ENV.fetch('WORKER_PROCESSES', 4).to_i
else
1
end
end
end
# Configure application based on environment
puts "Current environment: #{AppConfig.environment}"
puts "Log level: #{AppConfig.log_level}"
puts "Cache enabled: #{AppConfig.cache_enabled?}"
puts "Worker processes: #{AppConfig.worker_processes}"🧪 Environment Variable Testing
Testing Environment Variables
ruby
# Test environment variable setting and getting
RSpec.describe 'Environment Variables' do
before do
@original_env = ENV.to_hash
end
after do
ENV.replace(@original_env)
end
it 'should get environment variable' do
ENV['TEST_VAR'] = 'test_value'
expect(ENV['TEST_VAR']).to eq('test_value')
end
it 'should provide default value' do
expect(ENV.fetch('NON_EXISTENT_VAR', 'default')).to eq('default')
end
it 'should handle required variables' do
expect { ENV.fetch('REQUIRED_VAR') }.to raise_error(KeyError)
end
end
# Simple test script
def test_environment_variables
puts "=== Environment Variable Test ==="
# Test basic operations
ENV['TEST_VAR'] = 'test_value'
puts "Set test variable: #{ENV['TEST_VAR']}"
# Test default value
default_value = ENV.fetch('NON_EXISTENT', 'default')
puts "Default value test: #{default_value}"
# Test existence check
exists = ENV.key?('PATH')
puts "PATH variable exists: #{exists}"
# Clean up test variable
ENV.delete('TEST_VAR')
puts "Test variable cleanup complete"
puts "=== Test Complete ==="
end
# Run test
test_environment_variables if __FILE__ == $0🎯 Best Practices
1. Using dotenv for Development Environment Variables
ruby
# Gemfile
# gem 'dotenv-rails' # Rails application
# gem 'dotenv' # Regular Ruby application
# .env file example
=begin
# Development environment configuration
DATABASE_URL=sqlite://localhost/development.db
API_KEY=dev-api-key
DEBUG=true
SECRET_KEY=dev-secret-key
=end
# Load dotenv (at application startup)
require 'dotenv/load' if development?
# Access environment variables
database_url = ENV['DATABASE_URL']
api_key = ENV['API_KEY']2. Environment Variable Documentation
ruby
# environment_variables.rb
class EnvironmentVariables
# Application environment variable documentation
VARIABLES = {
'DATABASE_URL' => {
description: 'Database connection URL',
required: true,
default: nil,
example: 'postgresql://user:pass@localhost/dbname'
},
'API_KEY' => {
description: 'Third-party API key',
required: false,
default: 'default-key',
example: 'sk-xxxxxxxxxxxxxxxxxxxxxxxx'
},
'PORT' => {
description: 'Server port',
required: false,
default: '3000',
example: '3000'
},
'RUBY_ENV' => {
description: 'Application environment',
required: false,
default: 'development',
example: 'development|production|test'
}
}.freeze
def self.document
puts "Application Environment Variable Documentation:"
puts "=" * 50
VARIABLES.each do |name, info|
puts "Variable name: #{name}"
puts " Description: #{info[:description]}"
puts " Required: #{info[:required] ? 'Yes' : 'No'}"
puts " Default: #{info[:default] || 'None'}"
puts " Example: #{info[:example]}"
puts
end
end
end
# Generate documentation
# EnvironmentVariables.document3. Environment Isolation
ruby
class EnvironmentManager
def self.setup_environment
case ENV.fetch('RUBY_ENV', 'development')
when 'development'
setup_development
when 'production'
setup_production
when 'test'
setup_test
else
puts "Unknown environment: #{ENV['RUBY_ENV']}"
end
end
private
def self.setup_development
puts "Setting up development environment"
# Development environment specific configuration
end
def self.setup_production
puts "Setting up production environment"
# Production environment specific configuration
disable_debug_output
enable_caching
end
def self.setup_test
puts "Setting up test environment"
# Test environment specific configuration
end
def self.disable_debug_output
# Disable debug output
end
def self.enable_caching
# Enable caching
end
end
# Call at application startup
EnvironmentManager.setup_environment📚 Next Steps
After mastering Ruby environment variables, we recommend continuing to learn:
- Ruby Variables - Learn more about variable types in Ruby
- Ruby Data Types - Learn Ruby's type system
- Ruby Configuration Management - Learn advanced configuration management techniques
- Ruby Application Deployment - Learn environment variable management in production
Continue your Ruby learning journey!