#

In 

# :calendar


The :calendar paginator combines the functionality of time-range and OFFSET paginators.

It enables cascade-filtering of the collection by time units (year, quarter, month, week, and day), followed by paginating the filtered collection using the :offset paginator.

calendar_app
calendar_app

Try it now!

  @calendar, @pagy, @records = pagy(:calendar, collection, year: {}, month: {}, offset: {})
  • @calendar is a specialized hash that contains the pagy time unit objects (e.g., :year and :month in this example).
  • @pagy is the object representing the current page of records.
  • @records is the paginated subset of the collection.
  • The :year and :month parameters create time unit objects (default options are used in this example).
  • :offset is the offset instance that paginates the time-filtered collection.

You must define a few simple methods in your app to configure and coordinate the objects created by the pagy method. Se the following examples and comments (adapted from the Calendar app code)

Controller
# Note: All time values must be instances of ActiveSupport::TimeWithZone.
# REQUIRED: return the start and end limits of the collection as a 2 items array
def pagy_calendar_period(collection)
  starting = collection.minimum(:created_at)
  ending   = collection.maximum(:created_at)
  [starting.in_time_zone, ending.in_time_zone]
end

# REQUIRED: return the collection filtered by a time period
def pagy_calendar_filter(collection, from, to)
  collection.where(created_at: from...to)
end

# OPTIONAL: return the array of counts per time unit
# If this method is defined, pagy  will add an extra 'empty-page' CSS class 
# to the links leading to empty pages, along with a title attribute containing information about each page link.
def pagy_calendar_counts(collection, unit, from, to)
  # If collection is in order: :desc, add the reverse: true option to the next line
  collection.group_by_period(unit, :created_at, range: from...to).count.values
end

# Example usage with default options.
def index
  @calendar, @pagy, @records = pagy(:calendar, collection,
                                    year:  {},
                                    month: {},
                                    offset: {})
end
view (template)
<!-- Calendar filtering -->
<%== @calendar[:year].nav %>
<%== @calendar[:month].nav %>

<!-- Pagy info extended for the calendar unit -->
<%== @pagy.info %> for <%== @calendar[:month].page_label(@pagy.page, format: '%B %Y') %>.

... Render @records here ...

<!-- Standard pagination for the selected month -->
<%== @pagy.nav %>

<p>Showtime: <%= @calendar.showtime %></p>
<a href="<%= @calendar.url_at(Time.zone.now) %>">Go to now</a>

The calendar configuration defines the calendar objects to be generated. These objects filter the collection by the selected time units.

You can include one or more Unit levels using keys like :year, :quarter, :month, :week, or :day. Assign each key a hash of unit options. Use an empty hash for default values, e.g., year: {}, month: {}, ....

# The disabled flag


The calendar is enabled by default. However, you can include an optional :disabled boolean flag in the configuration hash to disable the calendar bars. This is useful to display the regular pages of the collection whithout any fitering nor Calendar UI.

  • @calendar.url_at(time_with_zone, **options)
    • Returns a URL complete with all parameters for the pages in each filter bar that includes the given time. For example: @calendar.url_at(Time.zone.now) generates the filter bar URLs pointing to today.

    • If time is outside the pagination range it raises a Pagy::RangeError, however you can pass the fit_time: true option to avoid the error and get the url to the page closest to the passed time argument (first or last page).

  • @calendar.showtime
    • Displays the time of the smallest time unit currently visible on the calendar.
  • order: :desc
    • Sets the order of the unit, either :asc or :desc. Make sure to order your collection accordingly.
  • format: '<strftime>'
    • Change the label format for the unit links.

This is the optional configuration for the core :offset paginator. If omitted a default one will be created. It is always used, regardless of the :disabled flag value.

It is not subject to the restrictions mentioned in the Calendar configuration.

Pagy provides the calendar localization obly for en locales. For non-en locales pagy requires the rails-i18n to be installed.

Pass the locales that your app uses to the method localize_with_rails_i18n_gem in the pagy.rb initializer:

Pagy::Calendar.localize_with_rails_i18n_gem(*your_locales)