Paginator for Amber Framework
Add this to your application's shard.yml
:
dependencies:
shale:
github: c910335/shale
Note: Shale only supports Granite and PostgreSQL currently.
# config/initializers/paginator.cr
require "shale/amber" # for page helper
require "shale/granite" # for granite adapter
Shale.base_url = "https://base.url"
# src/controllers/application_controller.cr
class ApplicationController < Amber::Controller::Base
include Shale::Amber::PageHelper(Shale::Granite::Adapter)
end
# src/controller/sample_controller
class SampleController < ApplicationController
def index
samples = paginate Sample
# render your view with samples
end
end
Shale::Amber::PageHelper#paginate
reads parameters from params
and path from request.path
and adds links to response.headers
, then returns the paginated data.
name | type | required | default | value |
---|---|---|---|---|
page | number | false | 1 | |
per_page | number | false | 8 | |
sort | string | false | id |
must be one of the columns |
direction | string | false | desc |
asc or desc |
reference: RFC 5988 - Web Linking
Link: <https://base.url/samples?page=2&per_page=3&sort=id&direction=desc>; rel="prev",
<https://base.url/samples?page=4&per_page=3&sort=id&direction=desc>; rel="next",
<https://base.url/samples?page=1&per_page=3&sort=id&direction=desc>; rel="first",
<https://base.url/samples?page=8&per_page=3&sort=id&direction=desc>; rel="last"
# Global
Shale.base_url = "https://base.url" # required
Shale.path = "/path"
Shale.page = 1
Shale.per = 8
Shale.order = :id
Shale.direction = :desc
# Scoped
class SomeController
include Shale::Amber::PageHelper(Shale::Granite::Adapter)
shale_base_url = "https://base.url"
shale_path = "/path"
shale_page = 1
shale_per = 8
shale_order = :id
shale_direction = :desc
end
This is what Shale::Amber::PageHelper
looks like.
require "shale"
module Shale::Amber::PageHelper(Adapter)
include Shale::Paginator(Adapter)
def paginate(model)
paginate model do |p|
p.path request.path
p.page params["page"].to_i if params["page"]?
p.per params["per_page"].to_i if params["per_page"]?
p.order params["sort"] if params["sort"]?
p.direction params["direction"] if params["direction"]?
p.headers response.headers
end
end
end
You can change the source of path or parameters by building your own paginator.
- inherits
Shale::BaseAdapter
- implements
#count(model)
and#select(model)
with#page
,#per
,#order
and#direction
For example, this is an ArrayAdapter
.
require "shale"
class ArrayAdapter < Shale::BaseAdapter
def count(array)
array.size
end
def select(array)
sorted = if direction.to_s == "desc"
array.sort { |a, b| b[order] <=> a[order] }
else
array.sort { |a, b| a[order] <=> b[order] }
end
sorted[(page - 1) * per, per]
end
end
Which is useful to paginate Array(Hash(Symbol, Int32))
.
class ArrayPaginator
include Shale::Paginator(ArrayAdapter)
end
array = Array.new(10) do |i|
{:number => 10 - i}
end
paginated = ArrayPaginator.new.paginate array do |p|
p.page 2
p.per 3
p.order :number
p.direction :asc
end
pp paginated # => [{:number => 4}, {:number => 5}, {:number => 6}]
Since Shale depends on PostgreSQL, we run specs with Docker.
$ docker-compose build
$ docker-compose run migrate
$ docker-compose run spec
- Fork it (https://github.com/c910335/shale/fork)
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create a new Pull Request
- c910335 Tatsiujin Chin - creator, maintainer