Recentemente, tenho trabalhado com a API de groups e tenho algumas reflexões sobre paginação, especificamente no contexto de não-descoberta.
O contexto
Para maior clareza, por “contexto de descoberta” me refiro à paginação em list_controller.rb e tags_controller.rb, que utilizam métodos semelhantes construct_url_with para gerar URLs das páginas anterior e próxima.
Sobre esse assunto, esses métodos construct_url_with poderiam, talvez, ser combinados em um módulo incluído, dado que são bastante semelhantes; no entanto, essa paginação é bastante integral à geração de listas de tópicos, sendo, portanto, algo de um bucket separado.
O padrão
No contexto de não-descoberta, a paginação utiliza alguma variação deste padrão:
page = params[:page].to_i
page_size = 38
items = items.offset(page * page_size).limit(page_size)
Você pode ver uma versão desse padrão em vários controladores, por exemplo (não exaustivo):
- groups
- web hooks
- emails
- notifications
- directory items
- staff action logs
…
Há alguns problemas com a paginação ao usar esses endpoints a partir de um cliente de terceiros.
Os problemas
Específico: inclusão da URL “load more”
Alguns desses endpoints retornam uma URL “load more” (com a página “próxima”), mesmo que não haja mais páginas.
Por exemplo, há 9 grupos visíveis (para mim) no meta. No entanto, obteremos uma entrada “load_more_groups” com uma segunda página inexistente (a página “1” é a segunda página, já que a numeração de páginas efetivamente começa em 0) no .json dessa página:
https://meta.discourse.org/g.json
...
"total_rows_groups":9,
"load_more_groups":"/groups?page=1"
Isso poderia ser descrito como um “bug” do endpoint, pois um cliente de API frequentemente buscará usar uma URL “load more” ao iterar sobre as páginas, em vez de tentar lidar com a contagem de páginas por conta própria.
Geral: nomenclatura diferente, tratamento do tamanho da página e dados de paginação retornados
Mais geralmente, há bastante variação na nomenclatura de paginação, nos tamanhos de página e nos dados de paginação retornados em contextos de não-descoberta. Por exemplo:
- “page” é chamado de
:pageou:offset. - “número total de itens” às vezes é incluído como
total_rows_*, mas nem sempre é incluído e, às vezes, é chamado de outra coisa. - a maioria dos tamanhos de página é atribuída a variáveis localmente em suas ações relevantes e difere um pouco, o que significa que você precisa procurar por eles.
Sugestão
Agora, existem várias razões para muitas das coisas que mencionei. Muitos dos endpoints de não-descoberta são consumidos principalmente (ou apenas) pelo cliente do aplicativo Discourse e são adaptados para esse cliente. Isso faz sentido.
Dito isso, pode haver um movimento aqui que comece a mover incrementalmente a paginação de não-descoberta, particularmente para endpoints que são frequentemente consumidos por clientes externos (como groups), em direção a uma maior padronização, o que também facilitaria resolver problemas como a inclusão da URL “load more”.
Essencialmente, o que tenho em mente é um módulo “Pagination” que codifique o padrão e possa lidar com a paginação em alguns endpoints selecionados, começando talvez com Groups.
Eu poderia criar um PR para isso, mas achei melhor levantar o assunto primeiro para discussão.