こんにちは。
今回は、multi DB構成のRailsアプリケーションでridgepoleのタスクを実行する方法を紹介します。
multi DB構成とは
multi DB構成とは、複数のDBを使ってアプリケーションを構築することです。
Railsアプリケーションでは、Rails 6.0から複数のDBを使うことができるようになりました。
例えば複数のRailsアプリケーションで一部だけ共通のDBを使うことができるようになるといったメリットがあります。
multi DB構成のメリット、デメリットについてはまた別の記事で紹介したいと思います。
↑書きました
複数のWebアプリケーションで共通のユーザー情報を扱いたいときにどのように設計するべきか?3パターンのpros/consをまとめました
ridgepoleとは
ridgepoleとは、RailsアプリケーションでDBのマイグレーションを管理するためのツールです。
GitHub - ridgepole/ridgepole: Ridgepole is a tool to manage DB schema.
もともとはCookpad社が開発していたものですが、結構広く使われている印象です。
migrationファイルの管理、めんどくさいですもんね…
かくいう私もとりあえず新規のアプリケーションを作成する際には活用しています。
multi DBでridgepoleのタスクを実行する
さて、multi DBの技術選定をしているときに、ridgepoleが使用できるのか?という疑問が出てきたので調べていたのですが、ちゃんと対応していました。
TechRacho - 複数DBでridgepoleコマンドを実行するときは -s オプションを指定しよう
-s
オプションをつけることで、どのDBに対してタスクを実行するかを指定することができます。
よし、じゃあ既存のrakeタスクを書き換えよう!ということでやってみました。
元のrakeタスク
元のrakeタスクは以下のようになっていました。
namespace :ridgepole do
def rails_env
ENV.fetch('RAILS_ENV', 'development')
end
def tables_option
tables = ENV.fetch('TABLES', '').split(',')
tables.empty? ? [] : ['--tables', tables.join(',')]
end
desc 'Export schema definitions'
task :export do
sh 'ridgepole', '--config', 'config/database.yml', '--env', rails_env, '--export', '--split', '--output',
'db/schema/Schemafile'
end
desc 'Show difference between schema definitions and actual schema'
task :'dry-run' do
sh 'ridgepole', '--config', 'config/database.yml', '--env', rails_env, '--apply', '--dry-run', '--file',
'db/schema/Schemafile', *tables_option
end
desc 'Apply schema definitions'
task :apply do
sh 'ridgepole', '--config', 'config/database.yml', '--env', rails_env, '--apply', '--file', 'db/schema/Schemafile',
*tables_option
end
end
これで、bin/rails ridgepole:apply
と実行すれば、DBのマイグレーションができるようになっていました。
それ以外にも、bin/rails ridgepole:export
と実行すれば、DBのスキーマをファイルに出力することができますし、bin/rails ridgepole:dry-run
と実行すれば、DBのマイグレーションを実行する前に差分を確認することができます。
書き換えたrakeタスク
さて、これをmulti DB構成に対応させるためには、-s
オプションをつける必要があります。
namespace :ridgepole do # rubocop:disable Metrics/BlockLength
def rails_env
ENV.fetch('RAILS_ENV', 'development')
end
def tables_option
tables = ENV.fetch('TABLES', '').split(',')
tables.empty? ? [] : ['--tables', tables.join(',')]
end
desc 'Export schema definitions'
task :export, %w[database] do |_, args|
database = args.database.presence || 'primary'
schemafile = "db/schema/#{database}/Schemafile"
sh 'ridgepole', '--config', 'config/database.yml', '-s', database, '--env', rails_env, '--export', '--split',
'--output', schemafile
end
desc 'Show difference between schema definitions and actual schema'
task :'dry-run', %w[database] do |_, args|
database = args.database.presence || 'primary'
schemafile = "db/schema/#{database}/Schemafile"
sh 'ridgepole', '--config', 'config/database.yml', '-s', database, '--env', rails_env, '--apply', '--dry-run',
'--file', schemafile, *tables_option
end
desc 'Apply schema definitions'
task :apply, %w[database] do |_, args|
database = args.database.presence || 'primary'
schemafile = "db/schema/#{database}/Schemafile"
sh 'ridgepole', '--config', 'config/database.yml', '-s', database, '--env', rails_env, '--apply', '--file',
schemafile, *tables_option
end
end
環境変数で付与することもできるのですが、今回は引数で指定するようにしました。
何も付与しない場合は、primary
とすることで、デフォルトのDBに対してタスクを実行するようになっています。
これで、bin/rails ridgepole:apply
と実行すれば、デフォルトのDBに対してマイグレーションができるようになりました。
また、bin/rails ridgepole:apply[secondary]
と実行すれば、secondary
という名前のDBに対してマイグレーションができるようになりました。
今回はこのあたりで。