docs/guides/upgrade-guide.md
Pagy version 43 is a complete redesign of the legacy code. Its improvements make pagination a lot simpler and powerful, but require a quite different way to use it.
!!!success Follow this guide to upgrade your app in just a few minutes. Cherry-pick only what applies to your app: you can safely skip all the rest. !!!
Replace the
pagy.rbconfig file...
pagy.rb initializer as pagy-old.rbPagy::DEFAULT[...] lines from pagy-old.rb and paste/add them to pagy.rbPagy::DEFAULT[...] entries with Pagy::OPTIONS[...] in pagy.rbIn the next steps we will use the pagy-old.rb as the blueprint to guide most of the changes, and we will edit the new pagy.rb as needed.
Remove your used extras...
The new version doesn't use the extras anymore. They got integrated in the core code, and a few have been discontinued.
require 'pagy/extras/* in the pagy-old.rb file...pagy-old.rb.==- Extras
:::
==- array
{.compact}
| Search (old) | Replace with (new) |
|---|---|
pagy_array(...) | pagy(:offset,...) |
==- arel
{.compact}
| Search (old) | Replace with (new) |
|---|---|
pagy_arel(...) | pagy(:offset, count_over: true, ...) |
==- pagy
@pagy instance methods with more explicit names.{.compact}
| Search (old) | Replace with (new) |
|---|---|
pagy_nav_js(@pagy, ...) | @pagy.series_nav_js(...) |
pagy_combo_nav_js(@pagy, ...) | @pagy.input_nav_js(...) |
pagy_limit_selector_js(@pagy, ...) | @pagy.limit_tag_js(...) |
pagy_prev_url(@pagy, ...) | @pagy.page_url(:previous, ...) |
pagy_next_url(@pagy, ...) | @pagy.page_url(:next, ...) |
pagy_prev_a(@pagy, ...) | @pagy.previous_tag(...) |
pagy_next_a(@pagy, ...) | @pagy.next_tag(...) |
pagy_prev_link(@pagy, ...) | discontinued: implement manually |
pagy_next_link(@pagy, ...) | discontinued: implement manually |
size: ... | |
Pagy::OPTIONS[:size] = ... | slots: ... |
Pagy::OPTIONS[:slots] = ... | |
ends: false | |
Pagy::OPTIONS[:end] = false | compact: true |
Pagy::OPTIONS[:compact] = true |
==- bootstrap
@pagy instance methods with more explicit names.{.compact}
| Search (old) | Replace with (new) |
|---|---|
pagy_bootstrap_nav(@pagy, ...) | @pagy.series_nav(:bootstrap, ...) |
pagy_bootstrap_nav_js(@pagy, ...) | @pagy.series_nav_js(:bootstrap, ...) |
pagy_bootstrap_combo_nav_js(@pagy, ...) | @pagy.input_nav_js(:bootstrap, ...) |
size: ... | |
Pagy::OPTIONS[:size] = ... | slots: ... |
Pagy::OPTIONS[:slots] = ... | |
ends: false | |
Pagy::OPTIONS[:end] = false | compact: true |
Pagy::OPTIONS[:compact] = true |
pagy-bootstrap class has been removed from the input_nav_js body.==- bulma
@pagy instance methods with more explicit names.{.compact}
| Search (old) | Replace with (new) |
|---|---|
pagy_bulma_nav(@pagy, ...) | @pagy.series_nav(:bulma, ...) |
pagy_bulma_nav_js(@pagy, ...) | @pagy.series_nav_js(:bulma, ...) |
pagy_bulma_combo_nav_js(@pagy, ...) | @pagy.input_nav_js(:bulma, ...) |
size: ... | |
Pagy::OPTIONS[:size] = ... | slots: ... |
Pagy::OPTIONS[:slots] = ... | |
ends: false | |
Pagy::OPTIONS[:end] = false | compact: true |
Pagy::OPTIONS[:compact] = true |
is-centered CSS class has been removed.==- countless
{.compact}
| Search (old) | Replace with (new) |
|---|---|
pagy_countless(...) | pagy(:countless, ...) |
countless_minimal: true | |
Pagy::OPTIONS[:countless_minimal] = true | headless: true |
Pagy::OPTIONS[:headless] = true |
==- calendar
{.compact}
| Search (old) | Replace with (new) |
|---|---|
pagy_calendar(...) | pagy(:calendar, ...) |
Pagy::Calendar::OutOfRangeError | Pagy::RangeError |
flag: active: true | disabled: false |
config: pagy: ... | offset: ... |
pagy-old.rb file contains any localization configuration, then uncomment and customize the following line in the
pagy.rb initializer: Pagy::Calendar.localize_with_rails_i18n_gem(*your_locales).
rails-i18n to your Gemfile.Pagy::Calendar::*::DEFAULT. Pass the options to each unit when you paginate.==- elasticsearch_rails
pagy method:{.compact}
| Search (old) | Replace with (new) |
|---|---|
pagy_elasticsearch_rails(...) | pagy(:elasticsearch_rails, ...) |
Pagy.new_from_elasticsearch_rails(...) | pagy(:elasticsearch_rails, ...) |
elasticsearch_rails_search: ... | |
Pagy::OPTIONS[:elasticsearch_rails_search] = ... | search_method: ... |
Pagy::OPTIONS[:search_method] = ... |
pagy_search method name has been discontinued:
:elasticsearch_rails_pagy_search variable from your code.pagy_search method.==- meilisearch
pagy method:{.compact}
| Search (old) | Replace with (new) |
|---|---|
pagy_meilisearch(...) | pagy(:meilisearch, ...) |
Pagy.new_from_meilisearch(...) | pagy(:meilisearch, ...) |
meilisearch_search: ... | |
Pagy::OPTIONS[:meilisearch_search] = ... | search_method: ... |
Pagy::OPTIONS[:search_method] = ... |
pagy_search method name has been discontinued:
:meilisearch_pagy_search variable from your code.pagy_search method.==- searchkick
pagy method:{.compact}
| Search (old) | Replace with (new) |
|---|---|
pagy_searchkick(...) | pagy(:searchkick, ...) |
Pagy.new_from_searchkick(...) | pagy(:searchkick, ...) |
searchkick_search: ... | |
Pagy::OPTIONS[:searchkick_search] = ... | search_method: ... |
Pagy::OPTIONS[:search_method] = ... |
pagy_search method name has been discontinued:
:searchkick_pagy_search variable from your code.pagy_search method.==- headers
{.compact}
| Search (old) | Replace with (new) |
|---|---|
pagy_headers(...) | @pagy.headers_hash(...) |
pagy_headers_merge | response.headers.merge!(@pagy.headers_hash) |
headers: ... | |
Pagy::OPTIONS[:headers] = ... | headers_map: ... |
Pagy::OPTIONS[:headers_map] = ... |
:limit header default is now 'page-limit (it was 'page-items').
Pagy::OPTIONS[:headers_map] = { limit: 'page-items', ... } to preserve your current API, if it relays on old default values.==- jsonapi
{.compact}
| Search (old) | Replace with (new) |
|---|---|
pagy_jsonapi_links(@pagy, ...) | @pagy.urls_hash(...) |
nil links are now removed as the JSON:API specifications require.jsonapi: true option (in the initializer or pagy method).==- keyset
{.compact}
| Search (old) | Replace with (new) |
|---|---|
pagy_keyset(...) | pagy(:keyset, ...) |
pagy_keyset_first_url(@pagy, ...) | @pagy.page_url(:first, ...) |
pagy_keyset_next_url(@pagy, ...) | @pagy.page_url(:next, ...) |
filter_newest: ... | override compose_predicate |
:jsonify_keyset_attributes with :pre_serialize.
keyset_attributes argument, but it must modify the specific values directly. The lambda's return value is ignored. For example: ->(attrs) { attrs[:created_at] = attrs[:created_at].strftime('%F %T.%6N') }.==- limit
{.compact}
| Search (old) | Replace with (new) |
|---|---|
limit_param: :... (symbol value) | limit_key: '...' (string value) |
limit_extra: ... | delete |
max_limit: ... | delete |
max_limit: allowed_max_limit option (in the initializer or pagy method).==- metadata
{.compact}
| Search (old) | Replace with (new) |
|---|---|
pagy_metadata(@pagy, ...) | @pagy.data_hash(...) |
metadata: ... | |
Pagy::OPTIONS[:metadata] = ... | data_keys: ... |
Pagy::OPTIONS[:data_keys] = ... | |
data_key -> :scaffold_url | :url_template |
==- overflow
Pagy::OverflowError has been replaced by the Pagy::RangeError; however, it is no longer raised by default.Pagy::RangeError and serves an empty page by default.
pagy.overflow? is now the pagy.in_range? method, which checks/returns the opposite state/boolean.overflow: :last_page behavior has been discontinued because it provides nearly no benefit:
:overflow variable is not used anymore.raise_range_error: true.overflow: :empty_page or just required the overflow extra, simply remove it (this is now the default behavior).overflow: :last_page and still want this behavior despite the reasons above, see this How To Example.==- standalone
Replace the :url variable with the :request hash option. For example:
request: { base_url: 'http://www.example.com',
path: '/path',
params: { 'param1' => 1234 }, # The string-keyed hash params from the request
cookie: 'xyz' } # The 'pagy' cookie, only for keynav
==- i18n
Pagy.translate_with_the_slower_i18n_gem!.==- gearbox (discontinued)
/gearbox/ related code.==- size (discontinued)
==- trim (discontinued)
Update the API...
==- Search and replace
{.compact}
| Search (old) | Replace with (new) |
|---|---|
include Pagy::Backend | include Pagy::Method |
include Pagy::Frontend | (remove: integrated) |
pagy_nav(@pagy, ...) | @pagy.series_nav(...) |
Pagy.root. | Pagy::ROOT. |
page_param: :... (symbol value) | page_key: '...' (string value) |
pagy_info(@pagy, ...) | @pagy.info_tag(...) |
@pagy_locale = ... | Pagy::I18n = ... |
@pagy.vars | @pagy.options |
VariableError | OptionError |
<error>.variable | <error>.option |
fragment: '#...' (mandatory '#') | fragment: '...' (optional '#') |
count_args: ... | (remove: integrated) |
outset: ... | (remove: discontinued) |
cycle: ... | (remove: discontinued) |
==- Replace the :params variable...
Use the :querify option, which is a lambda that can modify the string-keyed params hash at will. It is a bit more verbose, but it's more powerful and low-level. It solves an incompatibility with the old high-level :params hash/lambda and improves performance. It is part of the URL Options group that gives you full and efficient control over the URL composition. For example:
# Old symbol-keyed, high-level hash variable
params: { a: 1, b: 2 }
# New string-keyed, low-level, direct modification of the params hash
querify: ->(p) { p.merge!('a' => 1, 'b' => 2) }
# It also allows to do things like:
querify = ->(p) { p.except!('not_useful').merge!('custom' => 'useful') }
==- Replace the *prev* abbreviated naming
Use *previous* in all the options, accessors, methods, etc.
===
Finalize the upgrade...
==- Javascript
If your pagy-old.rb contains any JavaScript setup, it should still work, so you can move it to the pagy.rb file, however, for apps with builders, consider using the new Pagy.sync and removing all the old entries from your JavaScript config files.
==- Stylesheets
The CSS for the default pagy helpers have new selectors and variables. See the new Stylesheets to interactively update your custom CSS.
!!!success CSS Frameworks Supported CSS frameworks (like Bootstrap and Bulma) don't require any change. !!!
==- Pagy::I18n and Locale Files
{{ include "snippets/mini-step" step: "•1" }} If your pagy-old.rb contains the Pagy::I18n setup, and the setup includes some custom dictionary file, then uncomment and set up the relevant Pagy::I18n lookup section in the pagy.rb file. (See the I18n docs for details)
{{ include "snippets/mini-step" step: "•2" }} Update your custom dictionary files (if any) to the new dictionary structure, or they won't work correctly.
{{ include "snippets/mini-step" step: "•3" }} Remove all the I18n code from the pagy-old.rb. All the locales are autoloaded when your app uses them.
==- Overriding
pagy-old.rb contains overridden methods, copy the methods over to the pagy.rb initializer, however, consider that:
You may want also to check these internal renaming:
{.compact}
| Search (old) | Replace with (new) |
|---|---|
pagy_url_for(@pagy | @pagy.page_url( |
pagy_anchor(pagy | pagy.a_lambda( |
pagy_t | Pagy::I18n.translate |
label_for | page_label |
label | page_label |
==- Delete the pagy-old.rb file
At this point, there should be no more code in the pagy-old.rb.
===
{{ include "snippets/ask-for-support" }}
!!!warning Please report any issue with this guide by opening a New Docs Issue. !!!