📝

Railsのconfigurationを調べてみた(5)

2021/02/20に公開

なに?

Railsのconfigurationはどんなものがあって、どういう挙動なのかを調べてみた。
今回調べたものはActiveRecordに含まれるconfigだけである。

# ActiveRecordに関するconfigurationは、以下のように`active_record`をはさむ。
config.active_record.cache_versioning = true

各項目の細かい挙動まで十分に調べきれてはいないが、よく設定する項目などは別途調べたい。

ばーじょん

  • Ruby ruby 2.7.2p137
  • Rails 6.1.2

いちらん

action_on_strict_loading_violation(symbol)

Rails6.1で導入されたStrict Loadingで、N+1を検知したときの挙動を指定する。
デフォルトは:raise

以下のサンプルコードを実行したときの挙動を見てみる。

# user = User.strict_loading.first
# user.posts.first

:raiseの場合は、以下のようなエラーが発生する。

ActiveRecord::StrictLoadingViolationError (`User` is marked for strict_loading. The `Post` association named `:posts` cannot be lazily loaded.):
app/controllers/dashboards_controller.rb:6:in `index'

:logの場合は、以下のようなデバッグログだけを出力する。

Strict loading violation: User is marked for strict loading. The Post association named :posts cannot be lazily loaded.

belongs_to_required_by_default(boolean)

belongs_toで設定したオブジェクトを、デフォルト必須にするかどうかを指定する。
デフォルトはfalse

ただし、5.0以降のデフォルト設定を読み込むとtrueになる。

なお、個別に設定したい場合は、belongs_to :hoge, optional: trueと指定すればよい。

cache_timestamp_format(symbol)

キャッシュのキーを生成するときの時間フォーマットを指定する。
デフォルトは:usec

指定できるsymbolは、以下を参照。
https://github.com/rails/rails/blob/bf8c59cd896b1bf98d0f3df356531fa4c163219f/activesupport/lib/active_support/core_ext/time/conversions.rb#L8-L26

一覧に設定したいフォーマットがない場合は、以下のように追加することも可能。

# config/initializers/time_formats.rb
Time::DATE_FORMATS[:month_and_year] = '%B %Y'

cache_versioning(boolean)

キャッシュのキーに、バージョン情報を含めるかを指定する。
デフォルトはfalse

ただし、5.2以降のデフォルト設定を読み込むとtrueになる。

通常updated_atを用いてバージョン情報を付加するのだが、更新するたびに新しいキーが生成されてしまうため、キャッシュストアの容量を圧迫してしまうことを懸念したようだ。

true, falseの挙動の違いは、以下の通り。

# true
irb(main):001:0> user = User.first
irb(main):002:0> user.cache_key
=> "users/1"
irb(main):003:0> user.cache_version
=> "20210220004037981030"
irb(main):004:0> user.cache_key_with_version
=> "users/1-20210220004037981030"

# false
irb(main):001:0> user = User.first
irb(main):002:0> user.cache_key
=> "users/1-20210220004037981030"
irb(main):003:0> user.cache_version
=> nil
irb(main):004:0> user.cache_key_with_version
=> "users/1-20210220004037981030"

check_schema_cache_dump_version(boolean)

schema_cache.ymlとの整合性をチェックするかを指定する。
デフォルトはtrue

schema_cache.ymlについては、use_schema_cache_dumpの項目で説明する。

schema_cache.ymlとDBの状態にズレがある場合は、以下のようなwarningログが出力される。

Ignoring /home/kehra/Develop/rails-sample/db/schema_cache.yml because it has expired. The current schema version is 20210217232526, but the one in the cache is 20210217232525.

collection_cache_versioning

cache_versioningのQueryバージョン。
デフォルトはfalse

ただし、6.0以降のデフォルト設定を読み込むとtrueになる。

挙動は以下のようになる。

irb(main):002:0> User.where(id: 1..).cache_key
   (0.4ms)  SELECT COUNT(*) AS "size", MAX("users"."updated_at") AS timestamp FROM "users" WHERE "users"."id" >= ?  [["id", 1]]
=> "users/query-b7585bc163fa97756ce4e06aa0ca1bc6"

database_resolver(class)

データベースの接続先を決めるResolverクラスを指定する。
デフォルトはActiveRecord::Middleware::DatabaseSelector::Resolver

デフォルトのResolverは、Primaryのread/writeとReplicaのreadの3種類をSQLや発行タイミングを見て切り替えている。

database_resolver_context(class)

database_resolverに渡すコンテキストを指定する。
デフォルトはActiveRecord::Middleware::DatabaseSelector::Resolver::Session

database_selector(hash)

database_resolverに渡すオプションを指定する。
デフォルトは未設定。

詳しくは、Rails Guideを参照。
https://guides.rubyonrails.org/v6.1/active_record_multiple_databases.html

default_connection_handler(class)

データベースのコネクションを管理するHandlerを指定する。
デフォルトはConnectionAdapters::ConnectionHandler.new

default_role(symbol)

接続先のデフォルトのロールを指定する。
デフォルトはconfig.active_record.writing_roleの値が設定される。

default_shard(symbol)

接続先のデフォルトのシャードを指定する。
デフォルトは:default

default_timezone(symbol)

接続時のtimezoneを指定する。
デフォルトは:utc

destroy_association_async_job(class)

dependent: :destroy_asyncを指定したときの削除ジョブを指定する。
デフォルトはActiveRecord::DestroyAssociationAsyncJob

dump_schemas(symbol, string)

db:structure:dumpタスクを実行したときの動作を指定する。
デフォルトは:schema_search_path

なお、本オプションはPostgreSQLでのみ利用可能である。

dump_schema_after_migration(boolean)

マイグレーションを実行したあとに、スキーマをダンプするかを指定する。
デフォルトはtrue

error_on_ignored_order(boolean)

ApplicationRecord.in_batchesを実行したときに、ApplicationRecord.orderが設定されたときの挙動を指定する。
デフォルトはfalse

これは、ApplicationRecord.in_batchesを実行したときに、強制的にorder(#{primary_key})が設定されるためで、意図しない挙動を通知するための仕組みである。

trueの場合は、以下のようなエラーが発生する。

ArgumentError (Scoped order is ignored, it's forced to be batch order.):
app/controllers/dashboards_controller.rb:5:in `map'
app/controllers/dashboards_controller.rb:5:in `index'

falseの場合は、以下のようなwarningログだけを出力する。

Scoped order is ignored, it's forced to be batch order.

has_many_inversing(boolean)

inverse_ofを設定したときに、意図しない挙動が行ってしまうバグがあったが、挙動が大きく変わってしまうため、オプションとなったようだ。
デフォルトはfalseで修正前の挙動となる。

ただし、6.1以降のデフォルト設定を読み込むとtrueになる。

どういうバグなのかを検証できなかったので、該当PRを記載しておく。
https://github.com/rails/rails/pull/37429

legacy_connection_handling(boolean)

データベースコネクションのハンドリングを従来の挙動にするかを指定する。
デフォルトはtrue

ただし、6.1以降のデフォルト設定を読み込むとfalseになる。

falseにすると、抽象クラスでのハンドリングが可能となる。

logger(class)

ロガークラスを指定する。
デフォルトはRails.loggerが設定される。

maintain_test_schema(boolean)

テスト実行時に、マイグレーション情報との差分をチェックするかを指定する。
デフォルトはtrue

trueで差分があった場合、db:test:prepareタスクを実行して、自動的に最新の状態に合わせようとする。

migration_error(symbol)

マイグレーション情報に差分があったときの挙動を指定する。
デフォルトは:page_load

:page_loadを指定した場合、リクエストのたびにマイグレーション情報をチェックし、差分を検知したらActiveRecord::PendingMigrationErrorをraiseする。

queues(object)

非同期ジョブのキューを詰めるオブジェクトを指定する。
デフォルトはActiveSupport::InheritableOptions.new

schema_format(symbol)

スキーマ情報をどういう形式で出力するかを指定する。
デフォルトは:ruby

:sqlを指定することも可能だが、ミドルウェアを変更する際に注意が必要。

strict_loading_by_default(boolean)

Rails6.1で導入されたStrict Loadingを全体で適用するかどうかを指定する。
デフォルトはfalse

個別に指定する場合は、.strict_loadingを呼び出す。

suppress_multiple_database_warning(boolean)

database.ymlが正しく読み込めなかったときのエラーを抑制するかどうかを指定する。
デフォルトはfalse

use_schema_cache_dump(boolean)

スキーマのキャッシュを使うかどうかを指定する。
デフォルトはtrueだが、キャッシュファイルが見つからない場合は、スキップされる。

スキーマのdumpは、db:schema:cache:dumpタスクで行い、db/schema_cache.ymlが生成される。
これにより、データベースにスキーマ情報を問い合わせなくてもよくなる。

timestamped_migrations(boolean)

マイグレーションファイルを作成するときに、timestampを付加するかどうかを指定する。
デフォルトはtrue

falseにすると、前のマイグレーションファイルの番号をインクリメントした番号を付加する。

verbose_query_logs(boolean)

クエリーがどこで設定されていたのかをdebugログに出力するかを指定する。
デフォルトはfalse

trueにした場合、以下のようなログが出力される。

Post Load (0.3ms)  SELECT "posts".* FROM "posts" ORDER BY "posts"."id" ASC LIMIT ?  [["LIMIT", 1]]
↳ app/controllers/dashboards_controller.rb:7:in `index'

warn_on_records_fetched_greater_than(integer)

レコードをfetchしたとき、warningをだす件数を指定する。
デフォルトは未設定。

指定した件数を超えたとき、以下のようなwarningログが出力される。

Query fetched 2 Post records: PRAGMA foreign_keys = ON;SELECT sqlite_version(*);SELECT "posts".* FROM "posts"

Discussion