Search code examples
ruby-on-railsrubykaminari

How to paginate custom resources with kaminari helpers?


I have some custom resources queried over a rest API. I would like to make use of kaminari's pagination view helpers (e.g. page links).

I understand kaminari can paginate array-like resources when they are all available, however, my resources are expensive to query and store all at once.


Solution

  • Found this article helpful but outdated: https://kirshatrov.com/2015/11/08/kaminari-custom-query/

    Ended up writing my own adapter:

    class KaminariAdapter
      def initialize(page)
        @page = page.to_i
        @limit = 1
      end
    
      def entries(page)
        raise "Must be implemented by subclass"
      end
    
      def total_count
        raise "Must be implemented by subclass"
      end
    
      def entry_name(*arg)
        @entry_name ||= 'entry'.freeze
      end
    
      def current_page
        @page
      end
    
      def total_pages
        @total_pages ||= (total_count.to_f / @limit).ceil
      end
    
      def limit_value
        @limit
      end
    
      def offset
        (@page - 1) * @limit
      end
    
      def offset_value
        offset
      end
    
      def all
        entries(@page)
      end
    
      def size
        all.count
      end
    end
    

    Children must implement entries(page) and total_count methods. Here's an example:

    class CustomPagination < KaminariAdapter
      def initialize(*args)
        super
        @all_entries = [1, 2, 3, 4, 5, 6, 7]
        @limit = 2
      end
    
      def entries(page)
        @all_entries[offset..(offset + @limit - 1)]
      end
    
      def total_count
        @all_entries.count
      end
    end
    

    Can be used like this:

    test_controller.rb

    def index
      @entries = CustomPagination.new(params[:page].to_i)
    end
    

    test/index.html.erb

    <% @entries.all.each do |entry| %>
      <%= entry %>
    <% end %> 
    
    <%= paginate @entries %>
    <%= page_entries_info @entries %>