Recientemente he estado trabajando con la API de groups y tengo algunas reflexiones sobre la paginación, específicamente en el contexto no de descubrimiento.
El contexto
Para mayor claridad, por “contexto de descubrimiento” me refiero a la paginación en list_controller.rb y tags_controller.rb, que utilizan métodos similares como construct_url_with para generar las URL de la página anterior y la siguiente.
Al respecto, estos métodos construct_url_with podrían combinarse en un módulo incluido, dado que son bastante similares; sin embargo, esta paginación es bastante integral a la generación de listas de temas, por lo que constituye un área separada.
El patrón
En el contexto no de descubrimiento, la paginación utiliza alguna versión de lo siguiente:
page = params[:page].to_i
page_size = 38
items = items.offset(page * page_size).limit(page_size)
Puedes ver una variante de este patrón en varios controladores, por ejemplo (no exhaustivo):
- groups
- web hooks
- emails
- notifications
- directory items
- staff action logs
…
Existen algunos problemas con la paginación al utilizar estos endpoints desde un cliente de terceros.
Los problemas
Específico: inclusión de la URL “load more”
Algunos de estos endpoints devuelven una URL “load more” (con la página “siguiente”), incluso si no hay más páginas.
Por ejemplo, hay 9 grupos visibles (para mí) en meta. Sin embargo, se obtiene una entrada “load_more_groups” con una segunda página inexistente (la página “1” es la segunda página, ya que la numeración de páginas efectivamente comienza en 0) en el .json de esa página:
https://meta.discourse.org/g.json
...
"total_rows_groups":9,
"load_more_groups":"/groups?page=1"
Esto podría describirse como un “error” del endpoint, ya que un cliente de API suele intentar utilizar una URL “load more” al iterar sobre las páginas, en lugar de intentar manejar el conteo de páginas por sí mismo.
General: diferente nomenclatura, manejo del tamaño de página y datos de paginación devueltos
De manera más general, hay bastante variación en la nomenclatura de la paginación, los tamaños de página y los datos de paginación que se devuelven en contextos no de descubrimiento. Por ejemplo:
- “page” se denomina
:pageo:offset. - “número total de elementos” a veces se incluye como
total_rows_*, pero no siempre se incluye y a veces se llama de otra manera. - la mayoría de los tamaños de página se asignan a variables localmente en su acción correspondiente y difieren ligeramente, lo que significa que hay que buscarlos.
Sugerencia
Ahora bien, hay varias razones para muchas de las cosas que he mencionado. Muchos de los endpoints no de descubrimiento se consumen principalmente (o exclusivamente) por el cliente de la aplicación Discourse y están adaptados a ese cliente. Eso tiene sentido.
Dicho esto, podría haber un movimiento que comience a mover incrementalmente la paginación no de descubrimiento, particularmente para endpoints que a menudo son consumidos por clientes externos (como groups), hacia una mayor estandarización, lo que también facilitaría abordar problemas como la inclusión de la URL “load more”.
Esencialmente, lo que tengo en mente es un módulo “Pagination” que codifique el patrón y pueda manejar la paginación en algunos endpoints seleccionados, quizás comenzando con Groups.
Podría hacer un PR para eso, pero pensé en plantearlo primero para discusión.