rails 6.1rcがリリースされたので、新機能のstrict_loading
機能をまとめました。
See: https://weblog.rubyonrails.org/releases/
1. #strict_loading
オブジェクトにmarkをつけることで、そのオブジェクトのアソシエーション遅延ロードした際に例外ActiveRecord::StrictLoadingViolationError
を発生させます。
$ dev = Developer.strict_loading.first
$ dev.audit_logs.to_a
=> ActiveRecord::StrictLoadingViolationError: Developer is marked as strict_loading and AuditLog cannot be lazily loaded.
See: https://github.com/rails/rails/pull/37400
2. has_many :projects, strict_loading: true
関連付けのoptionで設定する方法。
指定したアソシエーション全てで、遅延ロードした際に例外ActiveRecord::StrictLoadingViolationError
を発生させます。
class Developer < ApplicationRecord
has_many :projects, strict_loading: true
end
dev = Developer.first
dev.projects.first
# => ActiveRecord::StrictLoadingViolationError: The projects association is marked as strict_loading and cannot be lazily loaded.
See: https://github.com/rails/rails/pull/38541
3. self.strict_loading_by_default = true
モデル単位で指定する方法。
指定したモデル全体からのアソシエーション全てで、遅延ロードした際に例外ActiveRecord::StrictLoadingViolationError
を発生させます。
class Developer < ApplicationRecord
self.strict_loading_by_default = true
has_many :projects
end
dev = Developer.first
dev.projects.first
# => ActiveRecord::StrictLoadingViolationError Exception: Developer is marked as strict_loading and Project cannot be lazily loaded.
See: https://github.com/rails/rails/pull/39491
その他
strict_loding検知時の挙動で例外発生だけではなくlog出力が選択できるようになりました。
config.active_record.action_on_strict_loading_violation
enables raising or
logging an exception if strict_loading is set on an association. The default
value is:raise
in all environments. It can be changed to:log
to send
violations to the logger instead of raising.
config.active_record.action_on_strict_loading_violation = :log
See
https://github.com/rails/rails/pull/40511
https://edgeguides.rubyonrails.org/configuring.html#configuring-active-record
これにより、development, test環境では例外を発生させ、production環境ではlog出力に留めることが可能になりました。
WTFでの議論
N+1を発生させないような工夫についてはコミュニティでも活発に議論されています。
https://discuss.rubyonrails.org/t/n-1-queries-should-be-the-exception-not-the-easy-trap-to-fall-in/74537/14