[Rails] multi DBでridgepoleのタスクを実行する

2023/08/25

Rails

こんにちは。

今回は、multi DB構成のRailsアプリケーションでridgepoleのタスクを実行する方法を紹介します。

multi DB構成とは

multi DB構成とは、複数のDBを使ってアプリケーションを構築することです。

Railsアプリケーションでは、Rails 6.0から複数のDBを使うことができるようになりました。

複数のデータベースを使う - Railsガイド

例えば複数の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タスクは以下のようになっていました。

lib/tasks/ridgepole.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オプションをつける必要があります。

lib/tasks/ridgepole.rake
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に対してマイグレーションができるようになりました。

今回はこのあたりで。

Related Posts

複数アプリで共通ユーザーデータを保持する設計パターン3選

複数アプリで共通ユーザーデータを保持する設計パターン3選