require 'erb' require 'yaml' module Ridgepole class Config class << self def load(config, env = 'development') config = ENV.fetch(Regexp.last_match(1)) if config =~ /\Aenv:(.+)\z/ parsed_config = if File.exist?(config) parse_config_file(config) elsif (expanded = File.expand_path(config)) && File.exist?(expanded) parse_config_file(expanded) elsif Gem::Version.new(Psych::VERSION) >= Gem::Version.new('3.1.0.pre1') # Ruby 2.6 YAML.safe_load( ERB.new(config).result, permitted_classes: [], permitted_symbols: [], aliases: true ) else YAML.safe_load(ERB.new(config).result, [], [], true) end parsed_config = parse_database_url(config) unless parsed_config.is_a?(Hash) if parsed_config.key?(env.to_s) parsed_config.fetch(env.to_s) else parsed_config end end private def parse_config_file(path) yaml = ERB.new(File.read(path)).result if Gem::Version.new(Psych::VERSION) >= Gem::Version.new('3.1.0.pre1') # Ruby 2.6 YAML.safe_load( yaml, permitted_classes: [], permitted_symbols: [], aliases: true ) else YAML.safe_load(yaml, [], [], true) end end def parse_database_url(config) uri = URI.parse(config) %w[scheme user host path].each do |key| value = uri.send(key) if value.nil? || value.empty? key = 'database' if key == 'path' raise "Invalid config: '#{key}' is empty: #{config.inspect}" end end { 'adapter' => uri.scheme, 'username' => CGI.unescape(uri.user), 'password' => uri.password ? CGI.unescape(uri.password) : nil, 'host' => uri.host, 'port' => uri.port, 'database' => CGI.unescape(uri.path.sub(%r{\A/}, '')), } end end end end