forked from fixin.me/fixin.me
Use DATABASE_URL instead of temp database.yml for multi-db tests
Replace the RAILS_DATABASE_YML / Dir.mktmpdir approach with DATABASE_URL: - Read database config via Rails.application.config.database_configuration instead of manually parsing YAML+ERB - Build a DATABASE_URL from each test config and pass it to subprocesses; Rails merges it on top of the test: entry — no temp files needed - Remove non_test_configs, Dir.mktmpdir, and the require yaml/erb/tmpdir - Remove RAILS_DATABASE_YML override from config/application.rb(.dist) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -20,10 +20,6 @@ Bundler.require(*Rails.groups)
|
||||
|
||||
module FixinMe
|
||||
class Application < Rails::Application
|
||||
# Allow RAILS_DATABASE_YML to override the database config file path.
|
||||
# Used by the multi-database test runner (lib/tasks/test_databases.rake).
|
||||
config.paths['config/database'] = [ENV['RAILS_DATABASE_YML']] if ENV['RAILS_DATABASE_YML']
|
||||
|
||||
# Initialize configuration defaults for originally generated Rails version.
|
||||
config.load_defaults 7.0
|
||||
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
require 'yaml'
|
||||
require 'erb'
|
||||
require 'tmpdir'
|
||||
require 'uri'
|
||||
|
||||
# Multi-database test runner
|
||||
# ==========================
|
||||
@@ -25,9 +23,10 @@ require 'tmpdir'
|
||||
#
|
||||
# A single-database setup is unchanged: every task behaves exactly as before.
|
||||
#
|
||||
# The mechanism uses RAILS_DATABASE_YML — an env var read by
|
||||
# config/application.rb(.dist) to override Rails' database config path before
|
||||
# initialisation, giving each subprocess a clean, isolated database config.
|
||||
# Database configuration is read via Rails.application.config.database_configuration
|
||||
# so ERB interpolation and all Rails path overrides are respected automatically.
|
||||
# Each subprocess receives DATABASE_URL built from the selected config, which
|
||||
# Rails merges on top of the test: entry from database.yml — no temporary files needed.
|
||||
|
||||
module MultiDbTests
|
||||
ADAPTER_GEMS = {
|
||||
@@ -55,19 +54,8 @@ module MultiDbTests
|
||||
class << self
|
||||
# Returns {name => config_hash} for every key starting with "test".
|
||||
def test_configs
|
||||
@test_configs ||= begin
|
||||
db_file = Rails.root.join('config', 'database.yml')
|
||||
all = YAML.safe_load(ERB.new(db_file.read).result, aliases: true) || {}
|
||||
all.select { |k, v| k.to_s.start_with?('test') && v.is_a?(Hash) }
|
||||
end
|
||||
end
|
||||
|
||||
def non_test_configs
|
||||
@non_test_configs ||= begin
|
||||
db_file = Rails.root.join('config', 'database.yml')
|
||||
all = YAML.safe_load(ERB.new(db_file.read).result, aliases: true) || {}
|
||||
all.reject { |k, _| k.to_s.start_with?('test') }
|
||||
end
|
||||
@test_configs ||= Rails.application.config.database_configuration
|
||||
.select { |k, v| k.to_s.start_with?('test') && v.is_a?(Hash) }
|
||||
end
|
||||
|
||||
# Run rails +task_name+ for every configured test database.
|
||||
@@ -89,16 +77,12 @@ module MultiDbTests
|
||||
next
|
||||
end
|
||||
|
||||
Dir.mktmpdir('rails_test_') do |tmpdir|
|
||||
tmp_yml = File.join(tmpdir, 'database.yml')
|
||||
File.write(tmp_yml, non_test_configs.merge('test' => config).to_yaml)
|
||||
env = { 'RAILS_DATABASE_YML' => tmp_yml }
|
||||
env = { 'DATABASE_URL' => config_to_url(config) }
|
||||
|
||||
if system(env, 'bundle exec rails db:test:prepare')
|
||||
results[db_name] = system(env, 'rails', task_name) ? :pass : :fail
|
||||
else
|
||||
results[db_name] = :prepare_failed
|
||||
end
|
||||
if system(env, 'bundle exec rails db:test:prepare')
|
||||
results[db_name] = system(env, 'rails', task_name) ? :pass : :fail
|
||||
else
|
||||
results[db_name] = :prepare_failed
|
||||
end
|
||||
end
|
||||
|
||||
@@ -110,6 +94,28 @@ module MultiDbTests
|
||||
|
||||
private
|
||||
|
||||
# Build a DATABASE_URL string from a database.yml config hash.
|
||||
# Rails merges DATABASE_URL on top of the test: entry, so adapter and
|
||||
# connection details from the URL take precedence over the YAML file.
|
||||
def config_to_url(config)
|
||||
adapter = config['adapter'].to_s
|
||||
database = config['database'].to_s
|
||||
|
||||
return "sqlite3:#{database}" if adapter == 'sqlite3'
|
||||
|
||||
user = config['username']
|
||||
pass = config['password']
|
||||
host = config['host'] || 'localhost'
|
||||
port = config['port']
|
||||
socket = config['socket']
|
||||
|
||||
userinfo = user ? "#{URI.encode_www_form_component(user)}:#{URI.encode_www_form_component(pass.to_s)}@" : ''
|
||||
hostport = port ? "#{host}:#{port}" : host
|
||||
url = "#{adapter}://#{userinfo}#{hostport}/#{database}"
|
||||
url += "?socket=#{URI.encode_www_form_component(socket)}" if socket
|
||||
url
|
||||
end
|
||||
|
||||
def adapter_available?(adapter)
|
||||
require ADAPTER_GEMS.fetch(adapter, adapter)
|
||||
true
|
||||
|
||||
Reference in New Issue
Block a user