Module: ActiveRpc::Rpc::Concerns::Paginatable

Extended by:
ActiveSupport::Concern
Included in:
QueryBuilder
Defined in:
lib/active_rpc/rpc/concerns/paginatable.rb

Overview

The Paginatable concern provides methods for applying pagination to ActiveRecord queries in gRPC controllers.

It supports:

  • Standard pagination with page and per_page parameters

  • Integration with the Pagy gem if available

  • Pagination metadata for responses

Examples:

def list_users
  process_request do
    base_query = User.all
    query = apply_pagination(base_query, request.message)
    # ...
  end
end

Instance Method Summary collapse

Instance Method Details

#apply_pagination(query, params) ⇒ Object

Apply pagination to a query only if explicitly requested



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/active_rpc/rpc/concerns/paginatable.rb', line 28

def apply_pagination(query, params)
  return query unless pagination_params?(params)

  begin
    page, per_page = sanitized_page_params(params)
    base_options = defined?(Pagy::OPTIONS) ? Pagy::OPTIONS : Pagy::DEFAULT
    options = base_options.merge(rpc_pagy_options(page, per_page))
    pagy, records = Pagy::OffsetPaginator.paginate(query, options)
    @last_pagy = pagy
    records
  rescue StandardError => e
    Rails.logger.error("Error applying pagination: #{e.message}")
    # Return original query if pagination fails
    query
  end
end

#pagination_metadata(query, params, total_count = nil) ⇒ Object

Get pagination metadata



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/active_rpc/rpc/concerns/paginatable.rb', line 46

def (query, params, total_count = nil)
  # If Pagy was used, get metadata from it
  if defined?(@last_pagy) && @last_pagy
    return {
      total_count: @last_pagy.count,
      page: @last_pagy.page,
      per_page: @last_pagy.limit,
      total_pages: @last_pagy.last
    }
  end

  # If pagination is not requested, return metadata with all records
  unless params.respond_to?(:page) && params.respond_to?(:per_page) &&
         params.page.present? && params.per_page.present?
    total_count = query.count
    return {
      total_count: total_count,
      page: 1,
      per_page: total_count,
      total_pages: 1
    }
  end

  # Calculate total count and pages
  total_count ||= query.except(:limit, :offset).count

  # Validate and sanitize per_page parameter
  per_page = params.per_page.to_i
  if per_page <= 0
    Rails.logger.warn("Invalid per_page value: #{params.per_page}. Using default value.")
    per_page = ActiveRpc::Rpc.configuration.default_per_page || 20
  end

  # Ensure per_page doesn't exceed maximum allowed
  max_per_page = ActiveRpc::Rpc.configuration.max_per_page || 100
  per_page = [ per_page, max_per_page ].min

  # Calculate total pages safely
  total_pages = total_count > 0 ? (total_count.to_f / per_page).ceil : 1

  {
    total_count: total_count,
    page: params.page,
    per_page: per_page,
    total_pages: total_pages
  }
end