2018-04-16
【Rails】データベース名を明示せずにActiveRecordでMySQLに接続する
目次
環境
- Rails 5.1.6
- MySQL 5.7.21
状況
データベースはまだ存在しないが、ActiveRecordでMySQLへの接続だけは確立したい。
何も考えずに次のようなコードを実行すると...
ApplicationRecord.connection.execute("<なんかSQL>")
次のようなエラーが起こる。
ActiveRecord::NoDatabaseError: Unknown database '<データベース名>'
どうするか
このような場合は、次のようにすると比較的スッキリ書ける。
config = ApplicationRecord.connection_config
ApplicationRecord.establish_connection(config.merge(database: nil)) # ★
ApplicationRecord.connection.execute("<なんかSQL>")
- まず、
ActiveRecord::ConnectionHandling.connection_config
でDBの接続情報を取得する。database.ymlに書いた情報がHash形式で取得できる。 - その後、
ActiveRecord::ConnectionHandling#establish_connection
でデータベースに接続するのだが、この時Hash#merge
でdatabase
をnil
で上書きする。これで、データベースを明示せずにMySQLへの接続を確立できる。 - あとは
execute
で SQLが実行できる
こんなんいつ役に立つんじゃい
自分は以下のような状況で使った。
- 一時的に複数のデータベースを扱う必要があるRailsアプリケーションがある(そのためdatabase.ymlが2つある状況)
- 2つ目のデータベースの作成と削除も、rakeタスクでRailsらしく実行したい
bin/rails 2nd_db:create
とかそんな感じで
- 2つ目のデータベース用の基底クラス(
ActiveRecord::Base
を継承したクラス)があるので、この基底クラスからCREATE DATABASE <2つ目のデータベース>
を発行したい。だが単純に実行しようとすると先述の通りエラーになる。 - 実装の都合上、1つ目のデータベースに接続するApplicationRecordはできれば使いたくない
- そこでコレ
状況がニッチすぎて誰得な感じは否めないが、自分はそれなりに悩んだのでインターネットの海に放流しておこうと思った次第である。その他、エレガントな実装方法があれば教えてほしい。