slack-ruby/slack-ruby-bot-server

View on GitHub
lib/slack-ruby-bot-server/api/helpers/cursor_helpers.rb

Summary

Maintainability
B
4 hrs
Test Coverage
module SlackRubyBotServer
  module Api
    module Helpers
      module CursorHelpers
        extend ActiveSupport::Concern

        # apply cursor-based pagination to a collection
        # returns a hash:
        #   results: (paginated collection subset)
        #   next: (cursor to the next page)
        if SlackRubyBotServer::Config.mongoid?
          def paginate_by_cursor(coll, _options)
            raise 'Both cursor and offset parameters are present, these are mutually exclusive.' if params.key?(:offset) && params.key?(:cursor)

            results = { results: [], next: nil }
            coll = coll.skip(params[:offset].to_i) if params.key?(:offset)
            size = (params[:size] || 10).to_i
            coll = coll.limit(size)
            coll.scroll(params[:cursor]) do |record, next_cursor|
              results[:results] << record if record
              results[:next] = next_cursor.to_s
              break if results[:results].count >= size
            end
            results[:total_count] = coll.count if params[:total_count] && coll.respond_to?(:count)
            results
          end
        elsif SlackRubyBotServer::Config.activerecord?
          include Pagy::Cursor::Backend

          def paginate_by_cursor(coll, options)
            raise 'Both cursor and offset parameters are present, these are mutually exclusive.' if params.key?(:offset) && params.key?(:cursor)

            results = { results: [], next: nil }
            size = (params[:size] || 10).to_i
            results[:total_count] = coll.count(:all) if params[:total_count]
            coll = coll.offset(params[:offset].to_i) if params.key?(:offset)
            sort_options = {}
            cursor_direction = :after
            sort_order(options).each do |order|
              sort_options[order[:column]] = { reverse: true } if order[:direction] == :desc
              cursor_direction = :before if order[:column] == coll.primary_key && order[:direction] == :desc
            end
            cursor_vars = { items: size }
            cursor_vars[cursor_direction] = params[:cursor].to_i if params.key?(:cursor)
            pagy_cursor, coll = pagy_cursor(coll, cursor_vars, { order: sort_options })
            results[:results] = coll.to_a
            results[:next] = coll.last[:id].to_s if pagy_cursor.has_more?
            results
          end
        end

        def paginate_and_sort_by_cursor(coll, options = {})
          Hashie::Mash.new(paginate_by_cursor(sort(coll, options), options))
        end
      end
    end
  end
end