Skip to content

Commit

Permalink
Change database yml directly
Browse files Browse the repository at this point in the history
  • Loading branch information
dhh committed Sep 2, 2024
1 parent fc2e42a commit ae9555c
Show file tree
Hide file tree
Showing 4 changed files with 260 additions and 4 deletions.
60 changes: 58 additions & 2 deletions lib/generators/solid_cache/install/install_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class SolidCache::InstallGenerator < Rails::Generators::Base
desc: "Skip migrations"

def add_rails_cache
if (env_config = Pathname(destination_root).join("config/environments/production.rb")).exist?
if (env_config = app_root.join("config/environments/production.rb")).exist?
gsub_file env_config, /(# )?config\.cache_store = (:.*)/, "config.cache_store = :solid_cache_store"
end
end
Expand All @@ -16,9 +16,65 @@ def create_config_solid_cache_yml
template "config/solid_cache.yml"
end

def add_cache_db_to_database_yml
if app_root.join("config/database.yml").exist?
if app_is_using_sqlite?
gsub_file database_yml, /production:\s*<<: \*default.*/m, sqlite_database_config_with_cache
else
gsub_file database_yml, /production:\s*<<: \*default.*/m, generic_database_config_with_cache
end
end
end

def create_migrations
unless options[:skip_migrations]
rails_command "railties:install:migrations FROM=solid_cache", inline: true
rails_command "railties:install:migrations DB=cache FROM=solid_cache", inline: true
end
end

private
def app_root
Pathname.new(destination_root)
end

def database_yml
app_root.join("config/database.yml")
end

def app_is_using_sqlite?
database_yml.read.match?(/production:.*sqlite3/m)
end

def sqlite_database_config_with_cache
<<~YAML
production:
primary:
<<: *default
database: storage/production.sqlite3
cache:
<<: *default
database: storage/production_cache.sqlite3
migrations_paths: db/cache_migrate
YAML
end

def app_name_from_production_database_name
database_yml.read.scan(/database: (\w+)_production/).flatten.first
end

def generic_database_config_with_cache
app_name = app_name_from_production_database_name

<<~YAML
production:
primary: &production_primary
<<: *default
database: #{app_name}_production
username: #{app_name}
password: <%= ENV["#{app_name.upcase}_DATABASE_PASSWORD"] %>
cache:
<<: *production_primary
database: #{app_name}_production_cache
YAML
end
end
59 changes: 59 additions & 0 deletions test/configs/mysql-database.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# MySQL. Versions 5.5.8 and up are supported.
#
# Install the MySQL driver
# gem install mysql2
#
# Ensure the MySQL gem is defined in your Gemfile
# gem "mysql2"
#
# And be sure to use new-style password hashing:
# https://dev.mysql.com/doc/refman/5.7/en/password-hashing.html
#
default: &default
adapter: mysql2
encoding: utf8mb4
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: root
password:
host: <%= ENV.fetch("DB_HOST") { "127.0.0.1" } %>

development:
<<: *default
database: bongo_development

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
<<: *default
database: bongo_test

# As with config/credentials.yml, you never want to store sensitive information,
# like your database password, in your source code. If your source code is
# ever seen by anyone, they now have access to your database.
#
# Instead, provide the password or a full connection URL as an environment
# variable when you boot the app. For example:
#
# DATABASE_URL="mysql2://myuser:mypass@localhost/somedatabase"
#
# If the connection URL is provided in the special DATABASE_URL environment
# variable, Rails will automatically merge its configuration values on top of
# the values provided in this file. Alternatively, you can specify a connection
# URL environment variable explicitly:
#
# production:
# url: <%= ENV["MY_APP_DATABASE_URL"] %>
#
# Read https://guides.rubyonrails.org/configuring.html#configuring-a-database
# for a full overview on how database connection configuration can be specified.
#
production:
primary: &production_primary
<<: *default
database: bongo_production
username: bongo
password: <%= ENV["BONGO_DATABASE_PASSWORD"] %>
cache:
<<: *production_primary
database: bongo_production_cache
28 changes: 28 additions & 0 deletions test/configs/sqlite-database.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# SQLite. Versions 3.8.0 and up are supported.
# gem install sqlite3
#
# Ensure the SQLite 3 gem is defined in your Gemfile
# gem "sqlite3"
#
default: &default
adapter: sqlite3
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
timeout: 5000

development:
<<: *default
database: storage/development.sqlite3

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
<<: *default
database: storage/test.sqlite3


# Store production database in the storage/ directory, which by default
# is mounted as a persistent Docker volume in config/deploy.yml.
production:
<<: *default
database: storage/production.sqlite3
117 changes: 115 additions & 2 deletions test/lib/generators/solid_cache/solid_cache/install_generator_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,121 @@ class SolidCache::InstallGeneratorTest < Rails::Generators::TestCase

test "generator updates environment config" do
run_generator [ "--skip-migrations" ]
assert_file "#{destination_root}/config/solid_cache.yml", expected_config
assert_file "#{destination_root}/config/solid_cache.yml", expected_solid_cache_config
assert_file "#{destination_root}/config/environments/development.rb", /config.cache_store = :memory_store\n/
assert_file "#{destination_root}/config/environments/development.rb", /config.cache_store = :null_store\n/
assert_file "#{destination_root}/config/environments/test.rb", /config.cache_store = :null_store\n/
assert_file "#{destination_root}/config/environments/production.rb", /config.cache_store = :solid_cache_store\n/
end

test "generator updates sqlite database config" do
copy_database_config_fixture_to_destination_root "sqlite"
run_generator [ "--skip-migrations" ]
assert_file "#{destination_root}/config/database.yml", <<~YAML
# SQLite. Versions 3.8.0 and up are supported.
# gem install sqlite3
#
# Ensure the SQLite 3 gem is defined in your Gemfile
# gem "sqlite3"
#
default: &default
adapter: sqlite3
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
timeout: 5000
development:
<<: *default
database: storage/development.sqlite3
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
<<: *default
database: storage/test.sqlite3
# Store production database in the storage/ directory, which by default
# is mounted as a persistent Docker volume in config/deploy.yml.
production:
primary:
<<: *default
database: storage/production.sqlite3
cache:
<<: *default
database: storage/production_cache.sqlite3
migrations_paths: db/cache_migrate
YAML
end

test "generator updates mysql database config" do
copy_database_config_fixture_to_destination_root "mysql"
run_generator [ "--skip-migrations" ]
assert_file "#{destination_root}/config/database.yml", <<~YAML
# MySQL. Versions 5.5.8 and up are supported.
#
# Install the MySQL driver
# gem install mysql2
#
# Ensure the MySQL gem is defined in your Gemfile
# gem "mysql2"
#
# And be sure to use new-style password hashing:
# https://dev.mysql.com/doc/refman/5.7/en/password-hashing.html
#
default: &default
adapter: mysql2
encoding: utf8mb4
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: root
password:
host: <%= ENV.fetch("DB_HOST") { "127.0.0.1" } %>
development:
<<: *default
database: bongo_development
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
<<: *default
database: bongo_test
# As with config/credentials.yml, you never want to store sensitive information,
# like your database password, in your source code. If your source code is
# ever seen by anyone, they now have access to your database.
#
# Instead, provide the password or a full connection URL as an environment
# variable when you boot the app. For example:
#
# DATABASE_URL="mysql2://myuser:mypass@localhost/somedatabase"
#
# If the connection URL is provided in the special DATABASE_URL environment
# variable, Rails will automatically merge its configuration values on top of
# the values provided in this file. Alternatively, you can specify a connection
# URL environment variable explicitly:
#
# production:
# url: <%= ENV["MY_APP_DATABASE_URL"] %>
#
# Read https://guides.rubyonrails.org/configuring.html#configuring-a-database
# for a full overview on how database connection configuration can be specified.
#
production:
primary: &production_primary
<<: *default
database: bongo_production
username: bongo
password: <%= ENV["BONGO_DATABASE_PASSWORD"] %>
cache:
<<: *production_primary
database: bongo_production_cache
YAML
end

private
def expected_config
def expected_solid_cache_config
<<~YAML
default: &default
database: cache
Expand All @@ -46,5 +152,12 @@ def expected_config
<<: *default
YAML
end

def copy_database_config_fixture_to_destination_root(database)
FileUtils.cp(File.expand_path("../../../../configs/#{database}-database.yml", __dir__), Pathname.new(destination_root).join("config/database.yml"))
end

def expected_mysql_database_config
end
end
end

0 comments on commit ae9555c

Please sign in to comment.