ウェブエンジニア珍道中

日々の技術的に関する経験を書いていきます。脱線もしますが助けになれば幸いです。

Railsで特定のModelだけ別DBを操作するようにしてみた

システム間連携等の事情で、別DBを作ってデータを流し込みたくなったので実装してみました。

手順

例としてBookモデルを作り、別DBを対象にするようにします。

環境はmysqlです。元々使っているDBはmain_database、新しく使うDBはsub_databaseという名前にしています。

対象となるDBと、テーブルを作っておく

別DBによりmigrationの管理外なので、予めスキーマ(DB)とテーブルを作っておきます。

CREATE DATABASE sub_database;

use sub_database;

CREATE TABLE `books` (
  `id`         int(11) NOT NULL AUTO_INCREMENT,
  `name`       varchar(255) NOT NULL,
  `author`     varchar(255) NOT NULL,
  `created_at` datetime DEFAULT NULL,
  `updated_at` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

config/database.ymlに別DB用の設定を書く

元々の設定をベースに新しい設定項目を増やします。

環境(stagingとか)にprefixを付ける形で名付けるとRails.env + 名前の要領で指定できるので環境毎に用意がしやすいです。

今回は同じmysql内の違うデータベースに保存するので元の設定をベースにdatabaseの欄だけ上書きしたものを用意します。

# 元々の設定
development: &development
  adapter: mysql2
  database: main_database
  encoding: utf8mb4
  charset: utf8mb4
  username: test_user
  password: any_password
  host: localhost

# 追加する
another_db_development:
  <<: *default
  database: sub_database

モデルに別DB用の設定を使うように指定する

他のモデルと同様app/modelに定義します。

booksテーブルの場合Bookクラスといった要領で単数系→アッパーキャメルケースにしてあげましょう。勝手にテーブルを見つけてくれます。ここは元のRailsのお作法通りです。

class Book
  establish_connection("another_db_#{Rails.env}".to_sym)
end

establish_connectionconfig/database.ymlで作った設定を指定することで別のDBを参照するようにしています。

使ってみる

普通のmodelを使うときと同じノリでOKです。

Book.create(name: "こころ", author: "夏目漱石")

Book.first # ↑で作ったものが取れる

別DBなのでjoinは動きませんが、手軽にアクセスができる環境ができるのでRailsはすげーなーと改めて思いました。

migrationが別管理なので、今後の課題です。(別PJによる管理とかなら問題なさそう)