LoginSignup
3
3

More than 3 years have passed since last update.

rails 6.1から追加されるN+1問題発生を抑止するstrict_loading機能

Last updated at Posted at 2020-11-10

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

3
3
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
3
3