diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index 8e035afd5500a..2cce4f25c5c23 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,3 +1,11 @@ +* Introduce `mariadb-mysql` and `mariadb-trilogy` database options for `rails new` + + When used with the `--devcontainer` flag, these options will use `mariadb` as the database for the + Dev Container. The original `mysql` and `trilogy` options will use `mysql`. Users who are not + generating a Dev Container do not need to use the new options. + + *Andrew Novoselac* + * Deprecate `::STATS_DIRECTORIES`. The global constant `STATS_DIRECTORIES` has been deprecated in favor of diff --git a/railties/lib/rails/generators/database.rb b/railties/lib/rails/generators/database.rb index e36a0da286e32..78f9f2e95f943 100644 --- a/railties/lib/rails/generators/database.rb +++ b/railties/lib/rails/generators/database.rb @@ -3,25 +3,91 @@ module Rails module Generators class Database - DATABASES = %w( mysql trilogy postgresql sqlite3 ) + DATABASES = %w( mysql trilogy postgresql sqlite3 mariadb-mysql mariadb-trilogy ) + + module MySQL + def name + "mysql" + end + + def port + 3306 + end + + def service + { + "image" => "mysql/mysql-server:8.0", + "restart" => "unless-stopped", + "environment" => { + "MYSQL_ALLOW_EMPTY_PASSWORD" => "true", + "MYSQL_ROOT_HOST" => "%" + }, + "volumes" => ["mysql-data:/var/lib/mysql"], + "networks" => ["default"], + } + end + + def socket + @socket ||= [ + "/tmp/mysql.sock", # default + "/var/run/mysqld/mysqld.sock", # debian/gentoo + "/var/tmp/mysql.sock", # freebsd + "/var/lib/mysql/mysql.sock", # fedora + "/opt/local/lib/mysql/mysql.sock", # fedora + "/opt/local/var/run/mysqld/mysqld.sock", # mac + darwinports + mysql + "/opt/local/var/run/mysql4/mysqld.sock", # mac + darwinports + mysql4 + "/opt/local/var/run/mysql5/mysqld.sock", # mac + darwinports + mysql5 + "/opt/lampp/var/mysql/mysql.sock" # xampp for linux + ].find { |f| File.exist?(f) } unless Gem.win_platform? + end + + def host + "localhost" + end + end + + module MariaDB + def name + "mariadb" + end + + def port + 3306 + end + + def service + { + "image" => "mariadb:10.5", + "restart" => "unless-stopped", + "networks" => ["default"], + "volumes" => ["mariadb-data:/var/lib/mysql"], + "environment" => { + "MARIADB_ALLOW_EMPTY_ROOT_PASSWORD" => "true", + }, + } + end + end class << self def build(database_name) case database_name - when "mysql" then MySQL.new + when "mysql" then MySQL2.new when "postgresql" then PostgreSQL.new - when "trilogy" then MariaDB.new + when "trilogy" then Trilogy.new when "sqlite3" then SQLite3.new + when "mariadb-mysql" then MariaDBMySQL2.new + when "mariadb-trilogy" then MariaDBTrilogy.new else Null.new end end def all @all ||= [ - MySQL.new, + MySQL2.new, PostgreSQL.new, - MariaDB.new, SQLite3.new, + MariaDBMySQL2.new, + MariaDBTrilogy.new ] end end @@ -30,6 +96,10 @@ def name raise NotImplementedError end + def template + raise NotImplementedError + end + def service raise NotImplementedError end @@ -69,48 +139,11 @@ def volume "#{name}-data" end - module MySqlSocket - def socket - @socket ||= [ - "/tmp/mysql.sock", # default - "/var/run/mysqld/mysqld.sock", # debian/gentoo - "/var/tmp/mysql.sock", # freebsd - "/var/lib/mysql/mysql.sock", # fedora - "/opt/local/lib/mysql/mysql.sock", # fedora - "/opt/local/var/run/mysqld/mysqld.sock", # mac + darwinports + mysql - "/opt/local/var/run/mysql4/mysqld.sock", # mac + darwinports + mysql4 - "/opt/local/var/run/mysql5/mysqld.sock", # mac + darwinports + mysql5 - "/opt/lampp/var/mysql/mysql.sock" # xampp for linux - ].find { |f| File.exist?(f) } unless Gem.win_platform? - end - - def host - "localhost" - end - end - - class MySQL < Database - include MySqlSocket - - def name - "mysql" - end - - def service - { - "image" => "mysql/mysql-server:8.0", - "restart" => "unless-stopped", - "environment" => { - "MYSQL_ALLOW_EMPTY_PASSWORD" => "true", - "MYSQL_ROOT_HOST" => "%" - }, - "volumes" => ["mysql-data:/var/lib/mysql"], - "networks" => ["default"], - } - end + class MySQL2 < Database + include MySQL - def port - 3306 + def template + "config/databases/mysql.yml" end def gem @@ -135,6 +168,10 @@ def name "postgres" end + def template + "config/databases/postgresql.yml" + end + def service { "image" => "postgres:16.1", @@ -169,27 +206,11 @@ def feature_name end end - class MariaDB < Database - include MySqlSocket - - def name - "mariadb" - end - - def service - { - "image" => "mariadb:10.5", - "restart" => "unless-stopped", - "networks" => ["default"], - "volumes" => ["mariadb-data:/var/lib/mysql"], - "environment" => { - "MARIADB_ALLOW_EMPTY_ROOT_PASSWORD" => "true", - }, - } - end + class Trilogy < Database + include MySQL - def port - 3306 + def template + "config/databases/trilogy.yml" end def gem @@ -214,6 +235,10 @@ def name "sqlite3" end + def template + "config/databases/sqlite3.yml" + end + def service nil end @@ -239,8 +264,17 @@ def feature_name end end + class MariaDBMySQL2 < MySQL2 + include MariaDB + end + + class MariaDBTrilogy < Trilogy + include MariaDB + end + class Null < Database def name; end + def template; end def service; end def port; end def volume; end diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index ca8b184f2027a..39deff5dbee74 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -206,7 +206,7 @@ def credentials_diff_enroll end def database_yml - template "config/databases/#{options[:database]}.yml", "config/database.yml" + template database.template, "config/database.yml" end def db diff --git a/railties/lib/rails/generators/rails/db/system/change/change_generator.rb b/railties/lib/rails/generators/rails/db/system/change/change_generator.rb index e8c9d12e9fbfb..28ef35ca66d82 100644 --- a/railties/lib/rails/generators/rails/db/system/change/change_generator.rb +++ b/railties/lib/rails/generators/rails/db/system/change/change_generator.rb @@ -35,7 +35,7 @@ def initialize(*) end def edit_database_config - template("config/databases/#{options[:database]}.yml", "config/database.yml") + template(database.template, "config/database.yml") end def edit_gemfile diff --git a/railties/test/commands/db_system_change_test.rb b/railties/test/commands/db_system_change_test.rb index 29068cbbaa040..0f027a6d236e3 100644 --- a/railties/test/commands/db_system_change_test.rb +++ b/railties/test/commands/db_system_change_test.rb @@ -25,7 +25,7 @@ class Rails::Command::DbSystemChangeTest < ActiveSupport::TestCase assert_match <<~MSG.squish, output Invalid value for --to option. Supported preconfigurations are: - mysql, trilogy, postgresql, sqlite3. + mysql, trilogy, postgresql, sqlite3, mariadb-mysql, mariadb-trilogy. MSG end diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index 9eb16ccd4b55c..754b938f367e6 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -1369,9 +1369,65 @@ def test_devcontainer_mysql end end - def test_devcontainer_mariadb + def test_devcontainer_trilogy run_generator [ destination_root, "--devcontainer", "-d", "trilogy" ] + assert_compose_file do |compose_config| + assert_includes compose_config["services"]["rails-app"]["depends_on"], "mysql" + expected_mysql_config = { + "image" => "mysql/mysql-server:8.0", + "restart" => "unless-stopped", + "environment" => { + "MYSQL_ALLOW_EMPTY_PASSWORD" => "true", + "MYSQL_ROOT_HOST" => "%" + }, + "volumes" => ["mysql-data:/var/lib/mysql"], + "networks" => ["default"], + } + + assert_equal expected_mysql_config, compose_config["services"]["mysql"] + assert_includes compose_config["volumes"].keys, "mysql-data" + end + assert_devcontainer_json_file do |content| + assert_equal "mysql", content["containerEnv"]["DB_HOST"] + assert_includes(content["forwardPorts"], 3306) + end + assert_file("config/database.yml") do |content| + assert_match(/host: <%= ENV.fetch\("DB_HOST"\) \{ "localhost" } %>/, content) + end + end + + def test_devcontainer_mariadb_mysql + run_generator [ destination_root, "--devcontainer", "-d", "mariadb-mysql" ] + + assert_compose_file do |compose_config| + assert_includes compose_config["services"]["rails-app"]["depends_on"], "mariadb" + expected_mariadb_config = { + "image" => "mariadb:10.5", + "restart" => "unless-stopped", + "networks" => ["default"], + "volumes" => ["mariadb-data:/var/lib/mysql"], + "environment" => { + "MARIADB_ALLOW_EMPTY_ROOT_PASSWORD" => "true", + }, + } + + assert_equal expected_mariadb_config, compose_config["services"]["mariadb"] + assert_includes compose_config["volumes"].keys, "mariadb-data" + end + assert_devcontainer_json_file do |content| + assert_equal "mariadb", content["containerEnv"]["DB_HOST"] + assert_includes content["features"].keys, "ghcr.io/rails/devcontainer/features/mysql-client" + assert_includes(content["forwardPorts"], 3306) + end + assert_file("config/database.yml") do |content| + assert_match(/host: <%= ENV.fetch\("DB_HOST"\) \{ "localhost" } %>/, content) + end + end + + def test_devcontainer_mariadb_trilogy + run_generator [ destination_root, "--devcontainer", "-d", "mariadb-trilogy" ] + assert_compose_file do |compose_config| assert_includes compose_config["services"]["rails-app"]["depends_on"], "mariadb" expected_mariadb_config = { diff --git a/railties/test/generators/db_system_change_generator_test.rb b/railties/test/generators/db_system_change_generator_test.rb index 509d9a1a2ce4d..afff13b6730ba 100644 --- a/railties/test/generators/db_system_change_generator_test.rb +++ b/railties/test/generators/db_system_change_generator_test.rb @@ -28,7 +28,7 @@ class ChangeGeneratorTest < Rails::Generators::TestCase assert_match <<~MSG.squish, output Invalid value for --to option. Supported preconfigurations are: - mysql, trilogy, postgresql, sqlite3. + mysql, trilogy, postgresql, sqlite3, mariadb-mysql, mariadb-trilogy. MSG end @@ -159,6 +159,10 @@ class ChangeGeneratorTest < Rails::Generators::TestCase assert_match "curl libvips", content assert_no_match "default-libmysqlclient-dev", content end + end + + test "change to mariadb" do + run_generator ["--to", "mariadb-mysql"] assert_devcontainer_json_file do |content| assert_match "mariadb", content["containerEnv"]["DB_HOST"]