Rails active_model_serializer with pagination

Bruce Xinda Lin picture Bruce Xinda Lin · Apr 8, 2014 · Viewed 10.7k times · Source

I'm using active_model_serializer. Now I want to serialize an object with pagination, should I do the pagination logic in the controller or in the serializer?

If I choose to do the pagination in serializer, I need to pass the page_number and per_page to the serializer. How should I do that? My understanding is serializer only takes the model object.

Answer

lightswitch05 picture lightswitch05 · Apr 11, 2014

Single Use Solution

Regular serializers are only concerned with single items - not paginated lists. The most straight forward way to add pagination is in the controller:

customers = Customer.page(params[:page])
respond_with customers, meta: {
  current_page: customers.current_page,
  next_page: customers.next_page,
  prev_page: customers.prev_page,
  total_pages: customers.total_pages,
  total_count: customers.total_count
}

Reusable Solution

However, this is pretty tedious if you need pagination logic for multiple objects. Looking through the documentation for active_model_serializers you'll come across an ArraySerializer for serializing an array of objects. What I did was create pagination_serializer.rb using ArraySerializer to automatically add the meta tag for paginated arrays:

# my_app/app/serializers/pagination_serializer.rb
class PaginationSerializer < ActiveModel::Serializer::ArraySerializer
  def initialize(object, options={})
    meta_key = options[:meta_key] || :meta
    options[meta_key] ||= {}
    options[meta_key][:pagination] = {
      current_page: object.current_page,
      next_page: object.next_page,
      prev_page: object.prev_page,
      total_pages: object.total_pages,
      total_count: object.total_count
    }
    super(object, options)
  end
end

Once you have PaginationSerializer added to your rails app, you simple need to call it when you need pagination meta tags from your controller:

customers = Customer.page(params[:page])
respond_with customers, serializer: PaginationSerializer

Note: I wrote this to use Kaminari as the paginator. However, it can easily be modified to work with any pagination gem or custom solution.