Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
175 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
--- | ||
title: Metadata | ||
--- | ||
# Metadata Extra | ||
|
||
If your app uses ruby as pure backend and some javascript frameworks as the frontend (e.g. Vue.js, react.js, ...), then you may want to generate the whole pagination UI directly in javascript either with your own code or using some available component. | ||
|
||
This extra makes that easy and efficient by adding a single method to the backend. | ||
|
||
## Synopsis | ||
|
||
See [extras](../extras.md) for general usage info. | ||
|
||
In the `pagy.rb` initializer: | ||
|
||
```ruby | ||
require 'pagy/extras/metadata' | ||
``` | ||
|
||
In your controller action: | ||
|
||
```ruby | ||
pagy, records = pagy(Product.all) | ||
render json: { data: records, | ||
pagy: pagy_metadata(pagy) } | ||
``` | ||
|
||
## Files | ||
|
||
- [hash.rb](https://github.com/ddnexus/pagy/blob/master/lib/pagy/extras/metadata.rb) | ||
|
||
## Variables | ||
|
||
| Variable | Description | Default | | ||
|:------------|:-----------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ||
| `:metadata` | Array of names used to control the returned metadata | `[ :scaffold_url, :first_url, :prev_url, :page_url, :next_url, :last_url, :count, :page, :items, :vars, :pages, :last, :from, :to, :prev, :next, :series ]` (plus `:sequels` if defined) | | ||
|
||
As usual, depending on the scope of the customization, you can set the `:metadata` variable globally or for a single pagy instance. | ||
|
||
**IMPORTANT**: Don't rely on the broad default! You should explicitly set the `:metadata` variable with only the names that you will actually use in the frontend, for obvious performance reasons. | ||
|
||
### :scaffold_url key | ||
|
||
This is a special url string that you can use as the scaffold to build real page urls in your frontend (instead of producing them on the backend). | ||
|
||
It is a pagination url/path (complete with all the params) containing the `__pagy_page__` placeholder in place of the page number (e.g. `'/foo?page=__pagy_page__&bar=baz'`) | ||
|
||
You can generate all the actual links on the frontend by simply replacing the placeholder with the actual page number you want to link to. | ||
|
||
In javascript you can do something like: | ||
|
||
```js | ||
page_url = scaffold_url.replace(/__pagy_page__/, page_number) | ||
``` | ||
|
||
This is particularly useful when you want to build some dynamic pagination UI (e.g. similar to what the `pagy_*combo_js` generates), but right in your frontend app, saving backend resources with obvious performance benefits. | ||
|
||
**Notice**: for simple cases you might directly use the other few `:*_url` metadata instead of the `:scaffold_url`. | ||
|
||
## Methods | ||
|
||
This extra adds a single method to the `Pagy::Backend` (available in your controllers). | ||
|
||
### pagy_metadata(pagy, url=false) | ||
|
||
This method returns a hash with the keys/values defined by the `:metadata` variable. When true, the `url` boolean argument will cause all the `:*_url` metadata to be absolute instead of relative. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# See the Pagy documentation: https://ddnexus.github.io/pagy/extras/metadata | ||
# encoding: utf-8 | ||
# frozen_string_literal: true | ||
|
||
class Pagy | ||
# Add a specialized backend method for pagination metadata | ||
module Backend ; private | ||
|
||
METADATA = [ :scaffold_url, :first_url, :prev_url, :page_url, :next_url, :last_url, | ||
:count, :page, :items, :vars, :pages, :last, :from, :to, :prev, :next, :series ] | ||
METADATA << :sequels if VARS.key?(:steps) # :steps gets defined along with the #sequels method | ||
|
||
VARS[:metadata] = METADATA.dup | ||
|
||
include Helpers | ||
|
||
def pagy_metadata(pagy, url=false) | ||
names = pagy.vars[:metadata] | ||
(unknown = names - METADATA).empty? or raise(VariableError.new(pagy), "unknown metadata #{unknown.inspect}") | ||
scaffold_url = pagy_url_for(Frontend::MARK, pagy, url) | ||
metadata = {} | ||
names.each do |key| | ||
metadata[key] = case key | ||
when :scaffold_url ; scaffold_url | ||
when :first_url ; scaffold_url.sub(Frontend::MARK, 1.to_s) | ||
when :prev_url ; scaffold_url.sub(Frontend::MARK, pagy.prev.to_s) | ||
when :page_url ; scaffold_url.sub(Frontend::MARK, pagy.page.to_s) | ||
when :next_url ; scaffold_url.sub(Frontend::MARK, pagy.next.to_s) | ||
when :last_url ; scaffold_url.sub(Frontend::MARK, pagy.last.to_s) | ||
else pagy.send(key) | ||
end | ||
end | ||
metadata | ||
end | ||
|
||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# encoding: utf-8 | ||
# frozen_string_literal: true | ||
|
||
require_relative '../../test_helper' | ||
require 'pagy/extras/shared' # include :sequels in VARS[:metadata] | ||
require 'pagy/extras/metadata' | ||
require 'pagy/countless' | ||
|
||
describe Pagy::Backend do | ||
|
||
describe "#pagy_metadata" do | ||
|
||
before do | ||
@controller = MockController.new | ||
@collection = MockCollection.new | ||
end | ||
|
||
it 'defines all metadata' do | ||
Pagy::VARS[:metadata].must_equal [:scaffold_url, :first_url, :prev_url, :page_url, :next_url, :last_url, :count, :page, :items, :vars, :pages, :last, :from, :to, :prev, :next, :series, :sequels] | ||
end | ||
|
||
it 'returns the full pagy metadata' do | ||
pagy, _records = @controller.send(:pagy, @collection) | ||
@controller.send(:pagy_metadata, pagy).must_equal( | ||
{:scaffold_url=>"/foo?page=__pagy_page__", :first_url=>"/foo?page=1", :prev_url=>"/foo?page=2", :page_url=>"/foo?page=3", :next_url=>"/foo?page=4", :last_url=>"/foo?page=50", :count=>1000, :page=>3, :items=>20, :vars=>{:page=>3, :items=>20, :outset=>0, :size=>[1, 4, 4, 1], :page_param=>:page, :params=>{}, :anchor=>"", :link_extra=>"", :i18n_key=>"pagy.item_name", :cycle=>false, :steps=>false, :metadata=>[:scaffold_url, :first_url, :prev_url, :page_url, :next_url, :last_url, :count, :page, :items, :vars, :pages, :last, :from, :to, :prev, :next, :series, :sequels], :count=>1000}, :pages=>50, :last=>50, :from=>41, :to=>60, :prev=>2, :next=>4, :series=>[1, 2, "3", 4, 5, 6, 7, :gap, 50], :sequels=>{"0"=>[1, 2, "3", 4, 5, 6, 7, :gap, 50]}} | ||
) | ||
end | ||
|
||
it 'checks for unknown metadata' do | ||
pagy, _records = @controller.send(:pagy, @collection, metadata: [:page, :unknown_key]) | ||
proc { @controller.send(:pagy_metadata, pagy)}.must_raise Pagy::VariableError | ||
end | ||
|
||
it 'returns only specific metadata' do | ||
pagy, _records = @controller.send(:pagy, @collection, metadata: [:scaffold_url, :page, :count, :prev, :next, :pages]) | ||
@controller.send(:pagy_metadata, pagy).must_equal( | ||
{:scaffold_url=>"/foo?page=__pagy_page__", :page=>3, :count=>1000, :prev=>2, :next=>4, :pages=>50} | ||
) | ||
end | ||
|
||
end | ||
|
||
end |