lib/quirky-api/response/pagination.rb
def paginate_with_cursor(objects, options = {})
        return [objects, nil, nil] if objects.empty?

        options = cursor_pagination_options.merge(options)
        field_type = objects.klass.columns_hash[options[:field]].type
        last = objects.last.send(options[:field])

        if objects.is_a?(Array)
          start = objects.index { |obj| obj.send(options[:field]) == options[:cursor].to_i }
          paged_objects = objects.slice(start, start + per_page)
          prev_cursor = [0, start - per_page].max
        else
          id_field = options[:ambiguous_field] ? options[:ambiguous_field] : options[:field]
          if options[:reverse]
            predicate = '<='
            first = objects.first.send(options[:field])
          else
            predicate = '>='
            first = FIRST_OBJECT_MAPPING[field_type]
          end
          options[:cursor] ||= first.to_i

          # If the cursor is a date type, then convert it back into a date for comparison
          options[:cursor] = DateTime.strptime("#{options[:cursor]}", '%s') if field_type == ('datetime'.to_sym)

          paged_objects = objects.where("#{id_field} #{predicate} :cursor", {cursor: options[:cursor]})
          paged_objects = paged_objects.limit(options[:per_page]) if options[:per_page]

          # If the cursor option was not sent in, we are retrieving the first set, and the previous cursor is nil
          # If the cursor option was sent in, we use that as the previous cursor, but will retrieve only objects
          if (options[:cursor]) == first
            prev_cursor = nil
          else
            previous_predicate = options[:reverse] ? '>' : '<'
            previous_objects = objects.where("#{id_field} #{previous_predicate} :cursor", {cursor: options[:cursor]}).reverse_order
            previous_objects = previous_objects.limit(options[:per_page]) if options[:per_page]
            prev_cursor = previous_objects.last.send(options[:field])
          end
        end
        object_ids = paged_objects.map(&options[:field].to_sym).compact

        # If we are reverse sorting the objects, the cursor is the minimum id - 1 to point to the next object)
        # If we are sorting it regularly, the cursor is maximum id + 1 to point to the next object
        # This works even when the max + 1 or min - 1 id is not present as we run a >= or <= operation when
        # filtering records
        next_cursor = (options[:reverse] ? object_ids.min - 1 : object_ids.max + 1) rescue nil

        # If we have reached the last object, next_cursor should be nil
        if options[:reverse] && next_cursor && next_cursor < last
          next_cursor = nil
        elsif !options[:reverse] && next_cursor && next_cursor > last
          next_cursor = nil
        end

        if field_type == ('datetime'.to_sym)
          prev_cursor = prev_cursor.to_i unless prev_cursor.nil?
          next_cursor = next_cursor.to_i unless next_cursor.nil?
        end

        [paged_objects, next_cursor, prev_cursor]
      end
# Paginates data based on a cursor.
#
# @param objects [Array|Object] The object(s) to paginate.
# @param options [Hash] A hash of options that will overwrite
#                       +cursor_pagination_options+.
#
# @see cursor_pagination_options
#
Paginates data based on a cursor.
Paginates data based on a cursor .
def paginate_with_cursor(objects, options = {})
        return [objects, nil, nil] if objects.empty?
        options = cursor_pagination_options.merge(options)
        field_type = objects.klass.columns_hash[options[:field]].type
        last = objects.last.send(options[:field])
        if objects.is_a?(Array)
          start = objects.index { |obj| obj.send(options[:field]) == options[:cursor].to_i }
          paged_objects = objects.slice(start, start + per_page)
          prev_cursor = [0, start - per_page].max
        else
          id_field = options[:ambiguous_field] ? options[:ambiguous_field] : options[:field]
          if options[:reverse]
            predicate = '<='
            first = objects.first.send(options[:field])
          else
            predicate = '>='
            first = FIRST_OBJECT_MAPPING[field_type]
          end
          options[:cursor] ||= first.to_i
          options[:cursor] = DateTime.strptime("#{options[:cursor]}", '%s') if field_type == ('datetime'.to_sym)
          paged_objects = objects.where("#{id_field} #{predicate} :cursor", {cursor: options[:cursor]})
          paged_objects = paged_objects.limit(options[:per_page]) if options[:per_page]
          if (options[:cursor]) == first
            prev_cursor = nil
          else
            previous_predicate = options[:reverse] ? '>' : '<'
            previous_objects = objects.where("#{id_field} #{previous_predicate} :cursor", {cursor: options[:cursor]}).reverse_order
            previous_objects = previous_objects.limit(options[:per_page]) if options[:per_page]
            prev_cursor = previous_objects.last.send(options[:field])
          end
        end
        object_ids = paged_objects.map(&options[:field].to_sym).compact
        next_cursor = (options[:reverse] ? object_ids.min - 1 : object_ids.max + 1) rescue nil
        if options[:reverse] && next_cursor && next_cursor < last
          next_cursor = nil
        elsif !options[:reverse] && next_cursor && next_cursor > last
          next_cursor = nil
        end
        if field_type == ('datetime'.to_sym)
          prev_cursor = prev_cursor.to_i unless prev_cursor.nil?
          next_cursor = next_cursor.to_i unless next_cursor.nil?
        end
        [paged_objects, next_cursor, prev_cursor]
      end
def paginate_with_cursor ( objects , options = { } ) return [ objects , nil , nil ] if objects . empty? options = cursor_pagination_options . merge ( options ) field_type = objects . klass . columns_hash [ options [ :field ] ] . type last = objects . last . send ( options [ :field ] ) if objects . is_a? ( Array ) start = objects . index { | obj | obj . send ( options [ :field ] ) == options [ :cursor ] . to_i } paged_objects = objects . slice ( start , start + per_page ) prev_cursor = [ 0 , start - per_page ] . max else id_field = options [ :ambiguous_field ] ? options [ :ambiguous_field ] : options [ :field ] if options [ :reverse ] predicate = '<=' first = objects . first . send ( options [ :field ] ) else predicate = '>=' first = FIRST_OBJECT_MAPPING [ field_type ] end options [ :cursor ] ||= first . to_i options [ :cursor ] = DateTime . strptime ( "#{options[:cursor]}" , '%s' ) if field_type == ( 'datetime' . to_sym ) paged_objects = objects . where ( "#{id_field} #{predicate} :cursor" , { cursor : options [ :cursor ] } ) paged_objects = paged_objects . limit ( options [ :per_page ] ) if options [ :per_page ] if ( options [ :cursor ] ) == first prev_cursor = nil else previous_predicate = options [ :reverse ] ? '>' : '<' previous_objects = objects . where ( "#{id_field} #{previous_predicate} :cursor" , { cursor : options [ :cursor ] } ) . reverse_order previous_objects = previous_objects . limit ( options [ :per_page ] ) if options [ :per_page ] prev_cursor = previous_objects . last . send ( options [ :field ] ) end end object_ids = paged_objects . map ( & options [ :field ] . to_sym ) . compact next_cursor = ( options [ :reverse ] ? object_ids . min - 1 : object_ids . max + 1 ) rescue nil if options [ :reverse ] && next_cursor && next_cursor < last next_cursor = nil elsif ! options [ :reverse ] && next_cursor && next_cursor > last next_cursor = nil end if field_type == ( 'datetime' . to_sym ) prev_cursor = prev_cursor . to_i unless prev_cursor . nil? next_cursor = next_cursor . to_i unless next_cursor . nil? end [ paged_objects , next_cursor , prev_cursor ] end
Paginates data based on a cursor.
Paginates data based on a cursor .
# If the cursor is a date type, then convert it back into a date for comparison # If the cursor option was not sent in, we are retrieving the first set, and the previous cursor is nil # If the cursor option was sent in, we use that as the previous cursor, but will retrieve only objects # If we are reverse sorting the objects, the cursor is the minimum id - 1 to point to the next object) # If we are sorting it regularly, the cursor is maximum id + 1 to point to the next object # This works even when the max + 1 or min - 1 id is not present as we run a >= or <= operation when # filtering records # If we have reached the last object, next_cursor should be nil
objects
The object(s) to paginate.
The object ( s ) to paginate .
options
A hash of options that will overwrite +cursor_pagination_options+.
A hash of options that will overwrite + cursor_pagination_options + .
see
None