Aqui está a solução que eu escolhi. O truque foi usar
left outer join
(comando ruby ansioso_load) para usuários e tabela Block_date_periods, e incluindo aqueles usuários cujo campo start_date na tabela unida é NULL, obviamente porque eles não têm nenhum objeto de data bloqueado associado a eles. A consulta que eu uso:User.eager_load(:blocked_date_periods).
where("blocked_date_periods.start_date is null OR
not tsrange(
blocked_date_periods.start_date - '00:59:59'::interval,
blocked_date_periods.end_date + '00:59:59'::interval
) @> ?::timestamp",
Date.parse(DATE_STRING)).count
Eu tive que adicionar e subtrair 1 hora da data de início e término porque a consulta não queria abranger datas de término exatas por algum motivo, de modo que 26-12-2015 não foi incluído no período de 22-12-2015 a 16-12-2015 por algum motivo ainda estou para entender.
Por algum motivo não gosto dessa solução e gostaria de saber se existe uma consulta melhor e mais rápida do que a que tenho.