Skip to content

Commit 30545ac

Browse files
committed
Add pagination for People index using Kaminari
1 parent b0b6bdd commit 30545ac

13 files changed

+138
-9
lines changed

Gemfile

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ gem "jbuilder"
1414
gem "tzinfo-data", platforms: %i[ mingw mswin x64_mingw jruby ]
1515
gem 'slim-rails'
1616
gem "jsbundling-rails"
17+
gem "kaminari"
1718

1819
group :development, :test do
1920
# See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem

Gemfile.lock

+13
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,18 @@ GEM
115115
activesupport (>= 5.0.0)
116116
jsbundling-rails (1.3.1)
117117
railties (>= 6.0.0)
118+
kaminari (1.2.2)
119+
activesupport (>= 4.1.0)
120+
kaminari-actionview (= 1.2.2)
121+
kaminari-activerecord (= 1.2.2)
122+
kaminari-core (= 1.2.2)
123+
kaminari-actionview (1.2.2)
124+
actionview
125+
kaminari-core (= 1.2.2)
126+
kaminari-activerecord (1.2.2)
127+
activerecord
128+
kaminari-core (= 1.2.2)
129+
kaminari-core (1.2.2)
118130
logger (1.6.1)
119131
loofah (2.23.1)
120132
crass (~> 1.0.2)
@@ -290,6 +302,7 @@ DEPENDENCIES
290302
faker
291303
jbuilder
292304
jsbundling-rails
305+
kaminari
293306
pry-rails
294307
puma (~> 5.0)
295308
rails (~> 7.0.1)

app/controllers/people_controller.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
class PeopleController < ApplicationController
22

33
def index
4-
@people = Person.includes(:company)
4+
@people = Person.includes(:company).page(params[:page])
55
end
66

77
def new
+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
li.page-item
2+
= link_to_unless current_page.first?, raw(t 'views.pagination.first'), url, remote: remote, class: 'page-link'

app/views/kaminari/_gap.html.slim

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
li.page-item.disabled
2+
= link_to raw(t 'views.pagination.truncate'), '#', class: 'page-link'
+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
li.page-item
2+
= link_to_unless current_page.last?, raw(t 'views.pagination.last'), url, remote: remote, class: 'page-link'
+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
li.page-item
2+
= link_to_unless current_page.last?, raw(t 'views.pagination.next'), url, rel: 'next', remote: remote, class: 'page-link'

app/views/kaminari/_page.html.slim

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
- if page.current?
2+
li.page-item.active
3+
= content_tag :a, page, data: { remote: remote }, rel: page.rel, class: 'page-link'
4+
- else
5+
li.page-item
6+
= link_to page, url, remote: remote, rel: page.rel, class: 'page-link'
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
= paginator.render do
2+
nav
3+
ul.pagination
4+
== first_page_tag unless current_page.first?
5+
== prev_page_tag unless current_page.first?
6+
- each_page do |page|
7+
- if page.left_outer? || page.right_outer? || page.inside_window?
8+
== page_tag page
9+
- elsif !page.was_truncated?
10+
== gap_tag
11+
== next_page_tag unless current_page.last?
12+
== last_page_tag unless current_page.last?
+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
li.page-item
2+
= link_to_unless current_page.first?, raw(t 'views.pagination.previous'), url, rel: 'prev', remote: remote, class: 'page-link'

app/views/people/index.html.slim

+5-6
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,9 @@ table.table
1212
- @people.each do |person|
1313
tr
1414
th[scope="row"]= person&.id
15-
td= person.try(:name)
16-
td= person.try(:phone)
17-
td= person.try(:email)
18-
td= person.try(:company).try(:name)
19-
20-
15+
td= person&.name
16+
td= person&.phone_number
17+
td= person&.email
18+
td= person&.company&.name
2119

20+
= paginate @people
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Kaminari.configure do |config|
2+
config.default_per_page = 10
3+
end
+87-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,90 @@
11
require "rails_helper"
22

3-
describe "people/index.html.slim" do
4-
it "Displays the users"
3+
describe "people/index.html.slim", type: :view do
4+
5+
def generate_people(count)
6+
Kaminari.paginate_array(
7+
Array.new(count) do |i|
8+
Person.create(
9+
name: "Person #{i + 1}",
10+
phone_number: "1234567890",
11+
email: "person#{i + 1}@example.com",
12+
company: Company.create(name: "Test Company")
13+
)
14+
end
15+
)
16+
end
17+
18+
shared_examples "renders people table" do |pagination_controls|
19+
it "displays the heading 'Viewing people'" do
20+
expect(rendered).to have_selector("h2", text: "Viewing people")
21+
end
22+
23+
it "renders the table headers correctly" do
24+
expect(rendered).to have_selector("table.table thead tr") do
25+
expect(rendered).to have_selector("th", text: "ID")
26+
expect(rendered).to have_selector("th", text: "Name")
27+
expect(rendered).to have_selector("th", text: "Phone number")
28+
expect(rendered).to have_selector("th", text: "Email address")
29+
expect(rendered).to have_selector("th", text: "Company")
30+
end
31+
end
32+
33+
it "renders pagination controls as expected" do
34+
if pagination_controls
35+
expect(rendered).to have_selector("nav>ul.pagination")
36+
else
37+
expect(rendered).not_to have_selector("nav>ul.pagination")
38+
end
39+
end
40+
end
41+
42+
context "when there are more than 10 records" do
43+
let(:people) { generate_people(15) }
44+
before do
45+
assign(:people, people.page(1).per(10))
46+
render
47+
end
48+
49+
include_examples "renders people table", true
50+
51+
52+
it "renders each person's details in the table" do
53+
people.each_with_index do |person, index|
54+
row_selector = "table.table tbody tr:nth-child(#{index + 1})"
55+
56+
expect(rendered).to have_selector(row_selector) do |row|
57+
expect(row).to have_selector("th", text: person.id.to_s)
58+
expect(row).to have_selector("td", text: person.name)
59+
expect(row).to have_selector("td", text: person.phone_number)
60+
expect(row).to have_selector("td", text: person.email)
61+
expect(row).to have_selector("td", text: person.company.name)
62+
end
63+
end
64+
end
65+
end
66+
67+
context "when there are less than 10 records" do
68+
let(:people) { generate_people(5) }
69+
before do
70+
assign(:people, people.page(1).per(10))
71+
render
72+
end
73+
74+
include_examples "renders people table"
75+
76+
it "renders each person's details in the table" do
77+
people.each_with_index do |person, index|
78+
row_selector = "table.table tbody tr:nth-child(#{index + 1})"
79+
80+
expect(rendered).to have_selector(row_selector) do |row|
81+
expect(row).to have_selector("th", text: person.id.to_s)
82+
expect(row).to have_selector("td", text: person.name)
83+
expect(row).to have_selector("td", text: person.phone_number)
84+
expect(row).to have_selector("td", text: person.email)
85+
expect(row).to have_selector("td", text: person.company.name)
86+
end
87+
end
88+
end
89+
end
590
end

0 commit comments

Comments
 (0)