Rails Eager загружает одно и то же отношение несколько раз с разными условиями - PullRequest
0 голосов
/ 05 февраля 2020

У меня есть статья с несколькими комментариями

class Article < ApplicationRecord
  has_many :comments
end

Я нахожусь внутри схемы GraphQL и пытаюсь использовать гем https://github.com/Shopify/graphql-batch. Внутри я хочу внедрить готовую загрузку для нескольких экземпляров, как это

::ActiveRecord::Associations::Preloader.new.preload(articles, :comments)

Пока это работает нормально и устраняет n + 1 запросов.

Теперь я хочу, чтобы нагрузка утверждена и отклонена комментарии

article.comments.where(approved: false)
article.comments.where(approved: true)

Я мог бы определить отдельную область для каждого из случаев на Article и использовать его имя

::ActiveRecord::Associations::Preloader.new.preload(articles, :comments_approved)
::ActiveRecord::Associations::Preloader.new.preload(articles, :comments_disapproved)

Но когда я хочу иметь возможность фильтровать ЛЮБОЕ Сочетание условий, это становится утомительным. Подумайте о :comments_approved_yesterday, :comments_approved_today, :comments_approved_for_user_1 ...

Итак, я думал об определении динамической области видимости c для каждого экземпляра article и последующей предварительной загрузке этой динамически c именованная область действия в

::ActiveRecord::Associations::Preloader.new.preload(articles, dynamic_scope_name)

К сожалению, я не нашел способа добиться этого. Я попробовал это, используя некоторые методы private rails:

dynamic_scope_name = :comments_approved_yesterday
association = article.association(:comments).dup
article.send(:association_instance_set, dynamic_scope_name, association)

Но это не работает с энергичной загрузкой: когда я перебираю все статьи и загружаю комментарии для каждой статьи, он не использует предварительно загруженные данные:

articles.each { |article| article.association(:comments_approved_yesterday).reader.to_a }
=> SELECT `comments`.* FROM `comments` WHERE `comments`.`article_id` = 1
=> SELECT `comments`.* FROM `comments` WHERE `comments`.`article_id` = 2
=> SELECT `comments`.* FROM `comments` WHERE `comments`.`article_id` = 3

Есть ли какой-либо способ четко определить ассоциацию на основе для каждого экземпляра в Rails?

...