Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Controller helper method for easier pagination #2

Open
nicolas-fricke opened this issue Mar 19, 2021 · 1 comment
Open

Controller helper method for easier pagination #2

nicolas-fricke opened this issue Mar 19, 2021 · 1 comment
Labels
enhancement New feature or request

Comments

@nicolas-fricke
Copy link
Member

Right now, to use the pagination in a Rails project, we have to write something like this in the controller:

def index
  @posts = Post.all
  paginated_posts = 
    RailsCursorPagination::Paginator
      .new(first: params[:first],
           before: params[:before],
           last: params[:last],
           after: params[:after])
      .fetch(with_total: params[:return_total])

  render json: paginated_posts
end

And this is without even supporting custom ordering. This is quite cumbersome, can lead to a lot of duplicated code, and therefore is also a source of potential bugs.

What we did in our project is to then add a helper method to our ApplicationController like so:

class ApplicationController < ActionController::API
  [...]

  private

  # Convenience method to paginate records with the RailsCursorPagination
  # gem and passing in the right parameter values.
  #
  # @param [ActiveRecord::Relation] records
  # @return [Hash]
  def paginate(records)
    RailsCursorPagination::Paginator
      .new(records,
           first: params[:first]&.to_i,
           after: params[:after],
           last: params[:last]&.to_i,
           before: params[:before])
      .fetch(with_total: ActiveModel::Type::Boolean.new.cast(params[:return_total]))
  end
end

this then allows our controllers to be as simple as

def index
  @posts = Post.all
  render json: paginate(@posts)
end

It would be great if such a method would be directly provided by the gem so that any client can make use of it. It could e.g. be part of a concern that a user can load into their controllers or directly include in their ApplicationController to have it available on all controllers.

We would also have to consider how to allow users to add ordering to this. But this should probably be an opt-in and maybe only allowing ordering on selected columns to avoid performance issues from API users that order on un-optimized columns. I could imagine an interface similar to:

paginate(@posts, allow_ordering: true, restrict_order_to: %i[id author])
@nicolas-fricke nicolas-fricke added the enhancement New feature or request label Mar 19, 2021
@myxoh
Copy link
Contributor

myxoh commented Jun 23, 2022

I'm interested in doing something like this - if we get the recent changes up, I'd be happy to upstream our current implementation that supports FE defined:

  • page size limit (within globally configured constaints)
  • order field and order direction (within configured constraints per endpoint)
  • pagination direction (before / after)

Our Concern (which we'd be happy to upstream) does something similar to the interface you presented, but relies on the changes we suggested on the PR i've just opened!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants