rails_cursor_pagination icon indicating copy to clipboard operation
rails_cursor_pagination copied to clipboard

Controller helper method for easier pagination

Open nicolas-fricke opened this issue 4 years ago • 1 comments
trafficstars

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 avatar Mar 19 '21 16:03 nicolas-fricke

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!

myxoh avatar Jun 23 '22 13:06 myxoh