RailsでGraphQL::Batch::Loaderを使うときの注意点です。
問題
N + 1問題を回避しようとしてGraphQL::Batch::Loaderを導入したが、N + 1問題が回避されなかった。
GraphQL::Batch::Loaderは以下のように、N + 1問題を回避するためのクラスです。
https://github.com/Shopify/graphql-batch#schema-configuration
原因
GraphQL::Batch::Loaderのforの引数にスコープ(ActiveRecord::Relation)を渡していたことが原因です。
GraphQL::Batch::Loaderでは、forの引数が同じ場合にBatch Loadされます。
同じというのは正確には、ハッシュのキーとして一致するという意味です。
ActiveRecord::Relationはハッシュのキーとして使えるように実装されていないので、実質的に同じでもハッシュのキーとして一致することはありません。
そのため、同じと認識されずBatch Loadされない。
解決策
ActiveRecord::Relationをハッシュのキーとして使えるようにするために、
以下のモンキーパッチを当てました。
module ActiveRecord
class Relation
def hash
to_sql.hash
end
def eql?(other)
self == other
end
end
end
Railsで実装検討されたこともあったみたいですが、放置されていました。
https://github.com/rails/rails/pull/33638