Если бы у нас была что-то вроде базы данных, которая хороша для подсчета строк ...
class Project < ApplicationRecord
has_many :stages
has_many :tasks, through: :stages
def self.with_counts
# subquery to fetch a count of the stages
stages = Stage
.where('stages.project_id = projects.id')
.where('stages.planned_end_date < ?', Time.current)
.select('COALESCE(COUNT(*), 0)')
.where(status: [0,2])
# subquery to fetch a count of the tasks
tasks = Task
.joins(:stage)
.select('COALESCE(COUNT(*), 0)')
.where(status: [0,2])
.where('tasks.planned_end_date < ?', Time.current)
.where('stages.project_id = projects.id')
select(
"projects.*",
"(#{stages.to_sql}) + (#{tasks.to_sql}) AS total_count"
).group(:id)
end
end
Это делает один запрос и выбирает total_count
через подзапрос:
SELECT projects.*,
(SELECT COALESCE(COUNT(*), 0)
FROM "stages"
WHERE ( stages.project_id = projects.id )
AND ( stages.planned_end_date < '2020-03-06 15:14:01.936655' )
AND "stages"."status" IN ( 0, 2 ))
+ (SELECT COALESCE(COUNT(*), 0)
FROM "tasks"
INNER JOIN "stages"
ON "stages"."id" = "tasks"."stage_id"
WHERE "tasks"."status" IN ( 0, 2 )
AND ( tasks.planned_end_date < '2020-03-06 15:14:01.941389' )
AND ( stages.project_id = projects.id )) AS total_count
FROM "projects"
GROUP BY "projects"."id"
ORDER BY "projects"."id" ASC
LIMIT $1
Я даже не собираюсь трогать ваш класс 'SubTask', поскольку это попытка FUBAR сделать то, что должно быть сделано с самоссылочной ассоциацией .