# frozen_string_literal: true

module CursorPaginatable
  extend ActiveSupport::Concern

  module ClassMethods
    # Defines a cursor paginator.
    #
    # This method will define a new method +name+, which accepts the keyword
    # arguments +last_id+ for defining the last id the cursor will operate on,
    # and +size+ for the amount of records it should return.
    #
    # @param name [Symbol] The name of the method for the cursor paginator
    # @param scope [Symbol] The name of the method which returns an
    #   ActiveRecord scope.
    #
    # @example
    # class User
    #   has_many :answers
    #
    #   include CursorPaginatable
    #   define_cursor_paginator :cursored_answers, :recent_answers
    #
    #   def recent_answers
    #     self.answers.order(:created_at).reverse_order
    #   end
    # end
    def define_cursor_paginator(name, scope, default_size: APP_CONFIG.fetch('items_per_page'))
      class_eval <<-RUBY, __FILE__, __LINE__ + 1
        def #{name}(*args, last_id: nil, size: #{default_size}, **kwargs)
          s = self.#{scope}(*args, **kwargs).limit(size)
          s = s.where(s.arel_table[:id].lt(last_id)) if last_id.present?
          s
        end
      RUBY
    end
  end
end