class Pagy

Experimental RBS support (using type sampling data from the type_fusion project).

# sig/pagy.rbs

class Pagy
  def initialize: (Hash vars) -> void
  def setup_vars: (Hash name_min) -> untyped
end

Core class

def self.root

Root pathname to get the path of Pagy files like templates or dictionaries
def self.root
  @root ||= Pathname.new(__dir__).freeze
end

def initialize(vars)

Experimental RBS support (using type sampling data from the type_fusion project).

def initialize: (count | Integer vars) -> void

This signature was generated using 1 sample from 1 application.

Merge and validate the options, do some simple arithmetic and set the instance variables
def initialize(vars)
  normalize_vars(vars)
  setup_vars(count: 0, page: 1, outset: 0)
  setup_items_var
  setup_pages_var
  setup_offset_var
  setup_params_var
  setup_request_path_var
  raise OverflowError.new(self, :page, "in 1..#{@last}", @page) if @page > @last
  @from   = [@offset - @outset + 1, @count].min
  @to     = [@offset - @outset + @items, @count].min
  @in     = [@to - @from + 1, @count].min
  @prev   = (@page - 1 unless @page == 1)
  @next   = @page == @last ? (1 if @vars[:cycle]) : @page + 1
end

def label

Allow the customization of the output (overridden by the calendar extra)
def label
  @page.to_s
end

def label_for(page)

Allow the customization of the output (overridden by the calendar extra)
def label_for(page)
  page.to_s
end

def normalize_vars(vars)

Apply defaults, cleanup blanks and set @vars
def normalize_vars(vars)
  @vars = DEFAULT.merge(vars.delete_if { |k, v| DEFAULT.key?(k) && (v.nil? || v == '') })
end

def series(size: @vars[:size], **_)

Return the array of page numbers and :gap items e.g. [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
def series(size: @vars[:size], **_)
  return [] if size.empty?
  raise VariableError.new(self, :size, 'to contain 4 items >= 0', size) \
        unless size.is_a?(Array) && size.size == 4 && size.all? { |num| !num.negative? rescue false } # rubocop:disable Style/RescueModifier
  # This algorithm is up to ~5x faster and ~2.3x lighter than the previous one (pagy < 4.3)
  left_gap_start  =     1 + size[0]   # rubocop:disable Layout/ExtraSpacing, Layout/SpaceAroundOperators
  left_gap_end    = @page - size[1] - 1
  right_gap_start = @page + size[2] + 1
  right_gap_end   = @last - size[3]
  left_gap_end    = right_gap_end  if left_gap_end   > right_gap_end
  right_gap_start = left_gap_start if left_gap_start > right_gap_start
  series          = []
  start           = 1
  if (left_gap_end - left_gap_start).positive?
    series.push(*start...left_gap_start, :gap)
    start = left_gap_end + 1
  end
  if (right_gap_end - right_gap_start).positive?
    series.push(*start...right_gap_start, :gap)
    start = right_gap_end + 1
  end
  series.push(*start..@last)
  series[series.index(@page)] = @page.to_s
  series
end

def setup_items_var

Setup @items (overridden by the gearbox extra)
def setup_items_var
  setup_vars(items: 1)
end

def setup_offset_var

Setup @offset based on the :gearbox_items variable
def setup_offset_var
  @offset = (@items * (@page - 1)) + @outset  # may be already set from gear_box
end

def setup_pages_var

Setup @pages and @last (overridden by the gearbox extra)
def setup_pages_var
  @pages = @last = [(@count.to_f / @items).ceil, 1].max
end

def setup_params_var

Setup and validate @params
def setup_params_var
  raise VariableError.new(self, :params, 'must be a Hash or a Proc', @params) \
        unless (@params = @vars[:params]).is_a?(Hash) || @params.is_a?(Proc)
end

def setup_request_path_var

def setup_request_path_var
  request_path = @vars[:request_path]
  return if request_path.to_s.empty?
  raise VariableError.new(self, :request_path, 'must be a bare path like "/foo"', request_path) \
        if !request_path.start_with?('/') || request_path.include?('?')
  @request_path = request_path
end

def setup_vars(name_min)

Experimental RBS support (using type sampling data from the type_fusion project).

def setup_vars: (items | Integer name_min) -> untyped

This signature was generated using 1 sample from 1 application.

Setup and validates the passed vars: var must be present and value.to_i must be >= to min
def setup_vars(name_min)
  name_min.each do |name, min|
    raise VariableError.new(self, name, ">= #{min}", @vars[name]) \
          unless @vars[name]&.respond_to?(:to_i) && instance_variable_set(:"@#{name}", @vars[name].to_i) >= min
  end
end