试用Rails6新增的小功能之一:112(database.yml警告部分)
首先
在第112段中试用Rails 6中的新增功能。这次我们讲解的是database.yml警告部分。
在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。
gem 'pg', '>= 0.18', '< 2.0'
gem 'mysql2'
执行 bundle install。
$ bundle install
请编辑database.yml文件。
修改database.yml文件.
添加MySQL的连接设置和PostgreSQL的连接设置。
通过环境变量,可以实现切换连接的功能。
在这里,关键是`<%= ENV.fetch(“DB”) { ‘postgresql’ } %>`这部分。
这个描述将导致警告出现。
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文件并输出结果。
yml = ERB.new(File.read(Rails.root.join('config/database.yml')))
print yml.result
运行脚本
执行脚本,没有出现任何错误并成功解析。
请注意下一行的开发代码: <<: *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无法推断你是否在使用多个数据库,从你的database.yml中…请简化你的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在启动之前读取database.yml文件并生成任务。在生成任务时,它不使用ERB而是使用DummyCompiler进行解析,并且据说DummyCompiler会在无法处理的情况下发出警告。
我该怎么办才好?
只要修改 ERB 部分,使其没有警告,那就可以了。然而,对于通常应该如何修改,笔者也不太清楚。
为了避免警告,进行修复。
通过修改如下,我们可以避免警告:
我们使用 if 语句添加了 default,并切换了使用开发环境等,这样修正后,我们不再使用 *default 来使用 ERB。
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
...
嘗試過的醬料 de
试验用的源码位于以下位置:
https://github.com/suketa/rails_sandbox/tree/try112_warn_database_yml – 存在警告的版本
https://github.com/suketa/rails_sandbox/tree/try112_warn_database_yml_fix – 已修复警告的版本
参考资料
-
- Warn if we can’t read the yaml to create database tasks
- Load YAML for rake tasks without parsing ERB