rails数据库.yml文件
#database #ruby #rails

我正在浏览"The Rails 7 Way",我阅读了以下段落:

Rails社区中的一种古老的最佳实践不是将config/database.yml存储在版本控制中。最重要的是,如果黑客获得对应用程序存储库的访问权限,则它们将在您的生产数据库中拥有所有连接设置。此外,团队的开发人员可能具有不同的开发和测试数据库设置。这使每个从事项目的开发人员都可以拥有自己的config/database.yml副本,该副本不存储在版本控件中。

这绝对是正确的:过去15年中,我与之合作的大多数Rails开发人员都认为这是版本控制系统中 not 存储config/database.yml的最佳实践。但是,这仍然是现代铁路应用程序的最佳实践吗?

让我们探索。

一些历史

首先,让我们看看在Rails的初始版本中,该文件的外观。这是从DHH's now famous 15 minute blog video from 2005拍摄的屏幕截图:

The original database.yml

最初的database.yml非常简单(很可能是故意的),基本上包含以下内容:

development:
  adapter: mysql
  database: blog_development
  host: localhost
  username: root
  password:

test:
  adapter: mysql
  database: blog_test
  host: localhost
  username: root
  password:

production:
  adapter: mysql
  database: blog_production
  host: localhost
  username: root
  password:

但是,人们很快注意到有很多重复,因此使用yaml Merge键去除重复变得很常见,因此上述database.yml将转换为:

defaults: &defaults
  adapter: mysql
  username: root
  password:
  host: localhost

development:
  <<: *defaults
  database: blog_development

test:
  <<: *defaults
  database: blog_test

production:
  <<: *defaults
  database: blog_production

这种方法变得很流行,并且被包括在"Rails Recipes" book by Chad Fowler中。我认为大卫试图在15分钟的视频(在3:09上)做类似的事情,但弄乱了YAML语法。

现在,显而易见的问题是您需要一个用户名和密码来连接到数据库进行开发,但并非所有开发人员都使用root数据库帐户,而通过源控制共享生产数据库密码是一个重要的安全问题。

为了解决此问题,开发人员通常选择了以下方法之一:

  • config/database.yml.example文件中检查并配置版本控制软件以忽略config/database.yml
  • config/database.yml文件中检查,但使用erb从环境变量中填充usernamepassword等值。

在这两种情况下,差异都很小,因为大多数团队都有某种自动化(如using the koude11 script)。但是,我看到了第一种方法的偏爱,因为:

过去十年的变化

存储诸如密码之类的秘密的问题不仅限于数据库,因为越来越多的应用程序开始与诸如​​Amazon S3之类的第三方服务集成。

存储凭据需要几个迭代:

由于在读取database.yml文件之前已加载凭据,因此我们可以重新访问defaults块,因此它使用加密的凭据:

defaults: &defaults
  adapter: mysql
  username: root
  password: <%= Rails.application.credentials.database_password %>
  host: localhost

但是,由于Rails 4.1有support for the koude21 environment variable which allowed you to override the koude0 settings

这对于像Heroku这样的平台很有用,因为现在它们可以提供整个连接路径的DATABASE_URL环境变量,并在您的config/database.yml中覆盖数据库名称(以前Heroku的方法是编写一个新文件,这可能会导致原因其他问题)。

改善默认值

Ruby在Rails上已经存在了近二十年,许多默认设置发生了很大变化,包括数据库设置,以使开发人员可以从开箱即用。

我认为,当涉及到初始设置时,我们可以在允许同事运行数据库的能力方面进行一些便利,但是他们认为合适,因为有些可能对无密码mysql root帐户不满意,有些人可能不满意不希望使用密码的额外麻烦。

mysql

如果您创建了一个新的Rails 7.0应用程序,则默认config/database.yml看起来像这样,假设您选择了MySQL作为数据库:

# MySQL. Versions 5.5.8 and up are supported.
#
# Install the MySQL driver
#   gem install mysql2
#
# Ensure the MySQL gem is defined in your Gemfile
#   gem "mysql2"
#
# And be sure to use new-style password hashing:
#   https://dev.mysql.com/doc/refman/5.7/en/password-hashing.html
#
default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password:
  socket: /var/run/mysqld/mysqld.sock

development:
  <<: *default
  database: blog_development

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
  <<: *default
  database: blog_test

# As with config/credentials.yml, you never want to store sensitive information,
# like your database password, in your source code. If your source code is
# ever seen by anyone, they now have access to your database.
#
# Instead, provide the password or a full connection URL as an environment
# variable when you boot the app. For example:
#
#   DATABASE_URL="mysql2://myuser:mypass@localhost/somedatabase"
#
# If the connection URL is provided in the special DATABASE_URL environment
# variable, Rails will automatically merge its configuration values on top of
# the values provided in this file. Alternatively, you can specify a connection
# URL environment variable explicitly:
#
#   production:
#     url: <%= ENV["MY_APP_DATABASE_URL"] %>
#
# Read https://guides.rubyonrails.org/configuring.html#configuring-a-database
# for a full overview on how database connection configuration can be specified.
#
production:
  <<: *default
  database: blog_production
  username: blog
  password: <%= ENV["BLOG_DATABASE_PASSWORD"] %>

这里有一些想法:

  • 我们不需要初始申请设置后的第一条评论行,因为mysql2 GEM将添加到Gemfile
  • 我们可以将usernamepasswordsocket设置移至默认的~/.my.cnf配置文件,从而使开发人员可以在看到fit fit
  • 时将其设置为
  • 在大多数情况下,我们将在生产环境中定义一个DATABASE_URL,覆盖数据库配置文件中我们拥有的任何设置,因此可以删除usernamepassword部分寻找什么

这是稍微更好的config/database.yml

default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  default_file: ~/.my.cnf

development:
  <<: *default
  database: blog_development

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
  <<: *default
  database: blog_test

# As with config/credentials.yml, you never want to store sensitive information,
# like your database password, in your source code. If your source code is
# ever seen by anyone, they now have access to your database.
#
# Instead, provide the password or a full connection URL as an environment
# variable when you boot the app. For example:
#
#   DATABASE_URL="mysql2://myuser:mypass@localhost/somedatabase"
#
# If the connection URL is provided in the special DATABASE_URL environment
# variable, Rails will automatically merge its configuration values on top of
# the values provided in this file. Alternatively, you can specify a connection
# URL environment variable explicitly:
#
#   production:
#     url: <%= ENV["MY_APP_DATABASE_URL"] %>
#
# Read https://guides.rubyonrails.org/configuring.html#configuring-a-database
# for a full overview on how database connection configuration can be specified.
#
production:
  <<: *default
  database: blog_production

这是一个示例~/.my.cnf文件:

[client]
user = andrei
password = AMERCE_sewage9borsch
socket = /var/run/mysqld/mysqld.sock

Postgresql

Rails生成的config/database.yml用于PostgreSQL数据库如下所示:

# PostgreSQL. Versions 9.3 and up are supported.
#
# Install the pg driver:
#   gem install pg
# On macOS with Homebrew:
#   gem install pg -- --with-pg-config=/usr/local/bin/pg_config
# On macOS with MacPorts:
#   gem install pg -- --with-pg-config=/opt/local/lib/postgresql84/bin/pg_config
# On Windows:
#   gem install pg
#       Choose the win32 build.
#       Install PostgreSQL and put its /bin directory on your path.
#
# Configure Using Gemfile
# gem "pg"
#
default: &default
  adapter: postgresql
  encoding: unicode
  # For details on connection pooling, see Rails configuration guide
  # https://guides.rubyonrails.org/configuring.html#database-pooling
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

development:
  <<: *default
  database: blog_development

  # The specified database role being used to connect to postgres.
  # To create additional roles in postgres see `$ createuser --help`.
  # When left blank, postgres will use the default role. This is
  # the same name as the operating system user running Rails.
  #username: blog

  # The password associated with the postgres role (username).
  #password:

  # Connect on a TCP socket. Omitted by default since the client uses a
  # domain socket that doesn't need configuration. Windows does not have
  # domain sockets, so uncomment these lines.
  #host: localhost

  # The TCP port the server listens on. Defaults to 5432.
  # If your server runs on a different port number, change accordingly.
  #port: 5432

  # Schema search path. The server defaults to $user,public
  #schema_search_path: myapp,sharedapp,public

  # Minimum log levels, in increasing order:
  #   debug5, debug4, debug3, debug2, debug1,
  #   log, notice, warning, error, fatal, and panic
  # Defaults to warning.
  #min_messages: notice

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
  <<: *default
  database: blog_test

# As with config/credentials.yml, you never want to store sensitive information,
# like your database password, in your source code. If your source code is
# ever seen by anyone, they now have access to your database.
#
# Instead, provide the password or a full connection URL as an environment
# variable when you boot the app. For example:
#
#   DATABASE_URL="postgres://myuser:mypass@localhost/somedatabase"
#
# If the connection URL is provided in the special DATABASE_URL environment
# variable, Rails will automatically merge its configuration values on top of
# the values provided in this file. Alternatively, you can specify a connection
# URL environment variable explicitly:
#
#   production:
#     url: <%= ENV["MY_APP_DATABASE_URL"] %>
#
# Read https://guides.rubyonrails.org/configuring.html#configuring-a-database
# for a full overview on how database connection configuration can be specified.
#
production:
  <<: *default
  database: blog_production
  username: blog
  password: <%= ENV["blog_DATABASE_PASSWORD"] %>

的评论比默认的mySQL版本要多一些,但这很可能是因为使用PostgreSQL和Rails开箱即用的设置可能不起作用。

您需要做的第一件事是创建一个与您的系统用户名匹配的超级用户帐户,因此您可以创建和破坏数据库(还有更多的粒度权限,但我们正在谈论开发机器,所以...) :

create user andrei superuser login password 'accursed5ground_BACILLI';

只需将andrei替换为您的帐户名。

然后,创建一个存储密码的~/.pgpass文件。这是一个例子:

localhost:*:*:andrei:accursed5ground_BACILLI

请记住,.pgpass文件的行为与~/.my.cnf文件的行为不相同,这意味着连接到localhost不会强迫usernamepassword,而是在连接host,port,port,database时提供密码usename匹配一行。

然后,我们可以在config/database.yml文件中应用相同的处理方法,但是我们不必指定default_file,因为Postgres使用了系统帐户并自动访问.pgpass文件:

default: &default
  adapter: postgresql
  encoding: unicode
  # For details on connection pooling, see Rails configuration guide
  # https://guides.rubyonrails.org/configuring.html#database-pooling
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

development:
  <<: *default
  database: blog_development


# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
  <<: *default
  database: blog_test

# As with config/credentials.yml, you never want to store sensitive information,
# like your database password, in your source code. If your source code is
# ever seen by anyone, they now have access to your database.
#
# Instead, provide the password or a full connection URL as an environment
# variable when you boot the app. For example:
#
#   DATABASE_URL="postgres://myuser:mypass@localhost/somedatabase"
#
# If the connection URL is provided in the special DATABASE_URL environment
# variable, Rails will automatically merge its configuration values on top of
# the values provided in this file. Alternatively, you can specify a connection
# URL environment variable explicitly:
#
#   production:
#     url: <%= ENV["MY_APP_DATABASE_URL"] %>
#
# Read https://guides.rubyonrails.org/configuring.html#configuring-a-database
# for a full overview on how database connection configuration can be specified.
#
production:
  <<: *default
  database: blog_production

就是这样!