LoginSignup
7
6

More than 3 years have passed since last update.

Rails6 のちょい足しな新機能を試す112(database.yml warning編)

Posted at

はじめに

Rails 6 に追加された新機能を試す第112段。 今回は、database.yml warning 編です。
Rails 6 では、複数データベースに対応していますが、 database.yml ファイルで複雑なERBが使われていると警告が出るようになっています。

Ruby 2.6.5, Rails 6.0.1 で確認しました。 (Rails 6.0.0 でこの修正が入ったようです。)

$ rails --version
Rails 6.0.1

今回は、警告を出すために、 環境変数 DB によって、 MySQLデータベースかPostgreSQLデータベースにアクセスを切り変えるということで試してみたいと思います。
複数データベースの機能は使いません。

Rails プロジェクトを作成する

$ rails new rails_sandbox
$ cd rails_sandbox

Gemfile に mysql2 と pg を追加する。

MySQL と PostgreSQL どちらでも接続できるように、 Gemfile に mysql2 と pg を追加します。

Gemfile
gem 'pg', '>= 0.18', '< 2.0'
gem 'mysql2'

bundle install を実行します。

$ bundle install

database.yml ファイルを編集する

database.yml を変更します。

MySQL 用の接続設定と PostgreSQL 用の接続設定を追加します。

環境変数によって、接続を切り変えられるようにします。

ここで、ポイントは、 <<: *<%= ENV.fetch("DB") { 'postgresql' } %> となっている部分です。
この記述によって警告が出るようになります。

config/database.yml
mysql: &mysql
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password:
  host: db_mysql

postgresql: &postgresql
  adapter: postgresql
  encoding: unicode
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  host: db_postgresql
  user: <%= ENV.fetch("POSTGRES_USER") %>
  password: <%= ENV.fetch("POSTGRES_PASSWORD") %>

development:
  <<: *<%= ENV.fetch("DB") { 'postgresql' } %>
  database: app_development
  ...

test:
  <<: *<%= ENV.fetch("DB") { 'postgresql' } %>
  database: app_test
  ...

production:
  <<: *<%= ENV.fetch("DB") { 'postgresql' } %>
  database: app_production
  ...

スクリプトを作成する

確認のためだけなのですが、 database.yml を ERB でパースして結果を出力するスクリプトを書いておきます。

scripts/parse_database_yml.rb
yml = ERB.new(File.read(Rails.root.join('config/database.yml')))
print yml.result

スクリプトを実行する

スクリプトを実行します。特にエラーもなくパースできています。

development: の次の行が、 <<: *postgresql と処理できていることに注意してください。

$ bin/rails runner scripts/parse_database_yml.rb
Running via Spring preloader in process 104
mysql: &mysql
  adapter: mysql2
  ...

postgresql: &postgresql
  adapter: postgresql
  ...

development:
  <<: *postgresql
  database: app_development
  ...

db:create を実行する

db:create を実行します。
Rails couldn't infer whether you are using multiple databases from your database.yml ... please simplify your ERB. と警告が出ます

$ bin/rails db:create
Rails couldn't infer whether you are using multiple databases from your database.yml and can't generate the tasks for the non-primary databases. If you'd like to use this feature, please simplify your ERB.
Created database 'app_development'
Created database 'app_test'

なぜ警告が出るのか

複数データベースに対応するために、 Rails は、 boot 完了する前に、 database.yml を読んで、task を生成しているそうです。task 生成する時点では、 ERB を使っておらず DummyCompiler を使って解析しており、この DummyCompiler では処理できない場合に警告を出すようにしたということらしいです。

どうすれば良いのか

結論としては、ERB の部分を警告が出ないように書き変えれば良いということになります。
では、一般的にどう書き変えれば良いのかは、筆者にもわかっていません。

ワーニングを出ないように修正する

今回の場合は、以下のように書き変えることで警告が出ないようにすることができました。
default を追加して if 文使って切り変えるようにして、 development などの環境では、 << *default を使って ERB を使わないように修正しました。

config/database.yml
mysql: &mysql
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password:
  host: db_mysql

postgresql: &postgresql
  adapter: postgresql
  encoding: unicode
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  host: db_postgresql
  user: <%= ENV.fetch("POSTGRES_USER") %>
  password: <%= ENV.fetch("POSTGRES_PASSWORD") %>

default: &default
  <% database = ENV.fetch("DB"){ 'postgresql' } %>
  <% if database == 'postgresql' %>
  <<: *postgresql
  <% else %>
  <<: *mysql
  <% end %>

development:
  <<: *default
  database: app_development
  ...

test:
  <<: *default
  database: app_test
  ...

production:
  <<: *default
  database: app_production
  ...

試したソース

試したソースは以下にあります。
https://github.com/suketa/rails_sandbox/tree/try112_warn_database_yml - 警告が出る方
https://github.com/suketa/rails_sandbox/tree/try112_warn_database_yml_fix - 警告が出ないように修正した方

参考情報

7
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
6