module Pagy::Backend

See also the extras if you need specialized methods to paginate Arrays or other collections

Add specialized backend methods to paginate array collections

Add specialized backend methods to paginate ElasticsearchRails searches

Add specialized backend methods to add pagination response headers

Add specialized backend methods to paginate Meilisearch results

Add a specialized backend method for pagination metadata

Add specialized backend methods to paginate Searchkick::Results

defines a dummy params method if not already defined in the including module

Constants

METADATA

Public Class Methods

included(controller) click to toggle source
# File lib/pagy/extras/standalone.rb, line 57
def self.included(controller)
  controller.define_method(:params){{}} unless controller.method_defined?(:params)
end

Private Instance Methods

pagy_arel(collection, vars={}) click to toggle source
# File lib/pagy/extras/arel.rb, line 8
def pagy_arel(collection, vars={})
  pagy = Pagy.new(pagy_arel_get_vars(collection, vars))
  [ pagy, pagy_get_items(collection, pagy) ]
end
pagy_arel_count(collection) click to toggle source
# File lib/pagy/extras/arel.rb, line 20
def pagy_arel_count(collection)
  if collection.group_values.empty?
    # COUNT(*)
    collection.count(:all)
  else
    # COUNT(*) OVER ()
    sql = Arel.star.count.over(Arel::Nodes::Grouping.new([]))
    collection.unscope(:order).limit(1).pluck(sql).first.to_i
  end
end
pagy_arel_get_vars(collection, vars) click to toggle source
# File lib/pagy/extras/arel.rb, line 13
def pagy_arel_get_vars(collection, vars)
  pagy_set_items_from_params(vars) if defined?(UseItemsExtra)
  vars[:count] ||= pagy_arel_count(collection)
  vars[:page]  ||= params[ vars[:page_param] || VARS[:page_param] ]
  vars
end
pagy_array(array, vars={}) click to toggle source

Return Pagy object and items

# File lib/pagy/extras/array.rb, line 10
def pagy_array(array, vars={})
  pagy = Pagy.new(pagy_array_get_vars(array, vars))
  [ pagy, array[pagy.offset, pagy.items] ]
end
pagy_array_get_vars(array, vars) click to toggle source

Sub-method called only by pagy_array: here for easy customization of variables by overriding

# File lib/pagy/extras/array.rb, line 16
def pagy_array_get_vars(array, vars)
  pagy_set_items_from_params(vars) if defined?(UseItemsExtra)
  vars[:count] ||= array.size
  vars[:page]  ||= params[ vars[:page_param] || VARS[:page_param] ]
  vars
end
pagy_elasticsearch_rails(pagy_search_args, vars={}) click to toggle source

Return Pagy object and items

# File lib/pagy/extras/elasticsearch_rails.rb, line 34
def pagy_elasticsearch_rails(pagy_search_args, vars={})
  model, query_or_payload, options, *called = pagy_search_args
  vars           = pagy_elasticsearch_rails_get_vars(nil, vars)
  options[:size] = vars[:items]
  options[:from] = vars[:items] * (vars[:page] - 1)
  response       = model.search(query_or_payload, **options)
  total          = response.respond_to?(:raw_response) ? response.raw_response['hits']['total'] : response.response['hits']['total']
  vars[:count]   = total.is_a?(Hash) ? total['value'] : total

  pagy = Pagy.new(vars)
  # with :last_page overflow we need to re-run the method in order to get the hits
  return pagy_elasticsearch_rails(pagy_search_args, vars.merge(page: pagy.page)) \
         if defined?(Pagy::UseOverflowExtra) && pagy.overflow? && pagy.vars[:overflow] == :last_page

  [ pagy, called.empty? ? response : response.send(*called) ]
end
pagy_elasticsearch_rails_get_vars(_collection, vars) click to toggle source

Sub-method called only by pagy_elasticsearch_rails: here for easy customization of variables by overriding the _collection argument is not available when the method is called

# File lib/pagy/extras/elasticsearch_rails.rb, line 53
def pagy_elasticsearch_rails_get_vars(_collection, vars)
  pagy_set_items_from_params(vars) if defined?(UseItemsExtra)
  vars[:items] ||= VARS[:items]
  vars[:page]  ||= (params[ vars[:page_param] || VARS[:page_param] ] || 1).to_i
  vars
end
pagy_headers(pagy) click to toggle source
# File lib/pagy/extras/headers.rb, line 17
def pagy_headers(pagy)
  pagy_headers_hash(pagy).tap do |hash|
    hash['Link'] = hash['Link'].map{|rel, link| %(<#{link}>; rel="#{rel}")}.join(', ')
  end
end
pagy_headers_hash(pagy) click to toggle source
# File lib/pagy/extras/headers.rb, line 23
def pagy_headers_hash(pagy)
  countless = defined?(Pagy::Countless) && pagy.is_a?(Pagy::Countless)
  rels = { 'first' => 1, 'prev' => pagy.prev, 'next' => pagy.next }
  rels['last'] = pagy.last unless countless
  url_str = pagy_url_for(pagy, PAGE_PLACEHOLDER, absolute: true)
  hash    = { 'Link' => rels.map do |rel, num| # filter_map if ruby >=2.7
                          next unless num
                          [ rel, url_str.sub(PAGE_PLACEHOLDER, num.to_s) ]
                        end.compact.to_h }
  headers = pagy.vars[:headers]
  hash[headers[:page]]  = pagy.page.to_s         if headers[:page]
  hash[headers[:items]] = pagy.vars[:items].to_s if headers[:items]
  unless countless
    hash[headers[:pages]] = pagy.pages.to_s if headers[:pages]
    hash[headers[:count]] = pagy.count.to_s if headers[:count]
  end
  hash
end
pagy_headers_merge(pagy) click to toggle source
# File lib/pagy/extras/headers.rb, line 13
def pagy_headers_merge(pagy)
  response.headers.merge!(pagy_headers(pagy))
end
pagy_meilisearch(pagy_search_args, vars = {}) click to toggle source

Return Pagy object and results

# File lib/pagy/extras/meilisearch.rb, line 29
def pagy_meilisearch(pagy_search_args, vars = {})
  model, term, options = pagy_search_args
  vars             = pagy_meilisearch_get_vars(nil, vars)
  options[:limit]  = vars[:items]
  options[:offset] = (vars[:page] - 1) * vars[:items]
  results          = model.search(term, **options)
  vars[:count]     = results.raw_answer['nbHits']

  pagy = Pagy.new(vars)
  # with :last_page overflow we need to re-run the method in order to get the hits
  return pagy_meilisearch(pagy_search_args, vars.merge(page: pagy.page)) \
    if defined?(Pagy::UseOverflowExtra) && pagy.overflow? && pagy.vars[:overflow] == :last_page

  [ pagy, results ]
end
pagy_meilisearch_get_vars(_collection, vars) click to toggle source

Sub-method called only by pagy_meilisearch: here for easy customization of variables by overriding the _collection argument is not available when the method is called

# File lib/pagy/extras/meilisearch.rb, line 47
def pagy_meilisearch_get_vars(_collection, vars)
  pagy_set_items_from_params(vars) if defined?(UseItemsExtra)
  vars[:items] ||= VARS[:items]
  vars[:page]  ||= (params[ vars[:page_param] || VARS[:page_param] ] || 1).to_i
  vars
end
pagy_metadata(pagy, deprecated_url=nil, absolute: nil) click to toggle source
# File lib/pagy/extras/metadata.rb, line 19
def pagy_metadata(pagy, deprecated_url=nil, absolute: nil)
  absolute = Pagy.deprecated_arg(:url, deprecated_url, :absolute, absolute) if deprecated_url
  names   = pagy.vars[:metadata]
  unknown = names - METADATA
  raise VariableError.new(pagy), "unknown metadata #{unknown.inspect}" \
        unless unknown.empty?

  scaffold_url = pagy_url_for(pagy, PAGE_PLACEHOLDER, absolute: absolute)
  {}.tap do |metadata|
    names.each do |key|
      metadata[key] = case key
                      when :scaffold_url then scaffold_url
                      when :first_url    then scaffold_url.sub(PAGE_PLACEHOLDER, 1.to_s)
                      when :prev_url     then scaffold_url.sub(PAGE_PLACEHOLDER, pagy.prev.to_s)
                      when :page_url     then scaffold_url.sub(PAGE_PLACEHOLDER, pagy.page.to_s)
                      when :next_url     then scaffold_url.sub(PAGE_PLACEHOLDER, pagy.next.to_s)
                      when :last_url     then scaffold_url.sub(PAGE_PLACEHOLDER, pagy.last.to_s)
                      else pagy.send(key)
                      end
    end
  end
end
pagy_searchkick(pagy_search_args, vars={}) click to toggle source

Return Pagy object and results

# File lib/pagy/extras/searchkick.rb, line 33
def pagy_searchkick(pagy_search_args, vars={})
  model, term, options, block, *called = pagy_search_args
  vars               = pagy_searchkick_get_vars(nil, vars)
  options[:per_page] = vars[:items]
  options[:page]     = vars[:page]
  results            = model.search(term, **options, &block)
  vars[:count]       = results.total_count

  pagy = Pagy.new(vars)
  # with :last_page overflow we need to re-run the method in order to get the hits
  return pagy_searchkick(pagy_search_args, vars.merge(page: pagy.page)) \
         if defined?(Pagy::UseOverflowExtra) && pagy.overflow? && pagy.vars[:overflow] == :last_page

  [ pagy, called.empty? ? results : results.send(*called) ]
end
pagy_searchkick_get_vars(_collection, vars) click to toggle source

Sub-method called only by pagy_searchkick: here for easy customization of variables by overriding the _collection argument is not available when the method is called

# File lib/pagy/extras/searchkick.rb, line 51
def pagy_searchkick_get_vars(_collection, vars)
  pagy_set_items_from_params(vars) if defined?(UseItemsExtra)
  vars[:items] ||= VARS[:items]
  vars[:page]  ||= (params[ vars[:page_param] || VARS[:page_param] ] || 1).to_i
  vars
end
pagy_set_items_from_params(vars) click to toggle source
# File lib/pagy/extras/items.rb, line 21
def pagy_set_items_from_params(vars)
  return if vars[:items]
  return unless vars.key?(:enable_item_extra) ? vars[:enable_item_extra] : VARS[:enable_items_extra]
  return unless (items = params[vars[:items_param] || VARS[:items_param]])                               # :items from :items_param
  vars[:items] = [items.to_i, vars.key?(:max_items) ? vars[:max_items] : VARS[:max_items]].compact.min   # :items capped to :max_items
end