Paged Lists

It's a common use case to need to transmit a long list of items from the backend to the frontend. In cases where the length of the list precludes transmitting the whole list verbatim, it's useful to chop the list up into "pages" and make those pages available to access by the frontend.

This is a common enough use case that Xing includes specialized serializers to support it. Here's how to use them.

The Overall Setup

Normally, when you're building a resource, you build a controller with the normal Rails actions ofshow, update, create, destroy and index. In a certain kind of way, the index action is actually a different resource. After all, you access the other actions by making requests to a URL like /fleas/1425326, and #index is used to respond to queries for /fleas.

What we're going to do as we switch over to a paginated list is to have two controllers. One will be the indiviual item controller (e.g. FleasController) and one will be the list controller. The item controller is exactly the same as a usual controller as discussed in the general Xing workflow, except that we remove the #index action. The list controller will have just #index and #show.

You'll need to make sure that the 'kaminari' gem is added to the backend/Gemfile as well.

Routes

Let's keep going with the "fleas" example. First, we'll add routes for the flea resources:

  resources :fleas, :except => [:index]
  resources :flea_pages, :only => [:index, :show], :param => :page

Controllers

We'll need two controllers. The first is the FleasController, which is exactly like a normal Xing controller, with the exception that the #index action is omitted.

The FleaPagesController is a little different from usual. Let's take a look:

class FleaPagesController < ApplicationController
  def index
    render json: FleaIndexSerializer.new(page_relation(1))
  end

  def show
    render json: FleaPageSerializer.new(page_relation(params[:page]))
  end

  private

  def page_relation(page_num)
    Fleas.order(:created_at).page(page_num)
  end
end

But what are those two extra serializers? Well...

Serializers

There are two extra serializers to write to complete the paged list. They're very simple:

class FleaIndexSerializer < Xing::Serializers::PagedIndex
  def self_link
    routes.flea_pages_path
  end

  def template_link
    routes.flea_page_path_rfc6570
  end
end

class FleaPageSerializer < Xing::Serializers::PagedList
  def item_serializer_class
    FleaSerializer
  end

  # This whole method is optional
  # In our example, we'll pass these option to the FleaSerializer to keep the list short
  def item_serializer_options
    { only: [:circus_trick, :weight] }
  end

  def template_link
    routes.flea_page_path_rfc6570
  end
end

Mappers

At the moment, paged lists are considered read only. You can set up a POST action on e.g. the :fleas route in order to create new items, as well as handling update and delete on the item controller. A streamlined way to handle re-ordering of items in a paged list is a feature we'd like to support, but there isn't yet a Xing tool to do that.

The good news is: having written the FleaMapper already, we're done!

The Frontend handling

To come...