Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
3
Help us understand the problem. What are the problem?
Organization

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

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

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
3
Help us understand the problem. What are the problem?