Ruby on Rails Pagination

I recently started coding with Ruby on Rails, one of the things that I wanted to create is a simple blog. Displaying the blog posts was simple enough, but later on the page started getting too long, so I figured I need to implement a simple pagination. In this tutorial I am going to show you how I did it, let’s get started.

We are going to query the data using Rails’ Active Record Query Interface then manupulate the result to show how many items should be displayed to the screen as well as the logic of the navigation that your users are going to use to to browse through the your posts. Assuming you have a “article” table already setup with a controller that looks like the following:

1
2
3
4
5
6
7
8
class ArticlesController < ApplicationController
    def index
    end
   
    def show
    end
    ...
end

Let’s add some logic to the index method:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
class ArticlesController < ApplicationController
   
    include ActionView::Helpers::TextHelper
   
    def index
        @pagination_content = ""
        @page_number = params["pageno"] ? params["pageno"].to_i : 1
         
        @page = @page_number
        @cur_page = @page
        @page -= 1
        # Set the number of results to display
        @per_page = 3
        @previous_btn = true
        @next_btn = true
        @first_btn = true
        @last_btn = true
        @start = @page * @per_page
       
        @pagination_content = ""
        @pagination_nav = ""
       
        @all_blog_posts = Article.limit(@per_page).offset(@start).order('title ASC')
        @count = Article.all.length
       
        if @all_blog_posts.present?
            @all_blog_posts.each do |post, value|
                @pagination_content += "
                    <h4>#{post.title}</h4>
                    #{truncate(strip_tags(post.text), :length => 500)}
                "

            end
        else
            @pagination_content += "<p class='bg-danger p-d'>No results</p>"
        end
       
        # Optional, wrap the output into a container
        @pagination_content = "<div class='cvf-universal-content'>#{@pagination_content}</div><br class = 'clear' />";

        @no_of_paginations = (@count.fdiv(@per_page)).ceil
       
        if @cur_page >= 7
            @start_loop = @cur_page - 3
            if @no_of_paginations > @cur_page + 3
                @end_loop = @cur_page + 3
            elsif @cur_page <= @no_of_paginations && @cur_page > @no_of_paginations - 6
                @start_loop = @no_of_paginations - 6
                @end_loop = @no_of_paginations
            else
                @end_loop = @no_of_paginations
            end
        else
            @start_loop = 1
            if @no_of_paginations > 7
                @end_loop = 7
            else
                @end_loop = @no_of_paginations
            end
        end

        # Pagination Buttons logic    
        @pagination_nav += "
            <div class='pagination-container'>
                <ul>"


        if @first_btn && @cur_page > 1
            @pagination_nav += "<li class='active'><a href = '#{@current_page_url}?pageno=1'>First</a></li>"
        elsif @first_btn
            @pagination_nav += "<li class='inactive'>First</li>"
        end

        if @previous_btn && @cur_page > 1
            @pre = @cur_page - 1
            @pagination_nav += "<li class='active'><a href = '#{@current_page_url}?pageno=#{@pre}'>Previous</a></li>"
        elsif @previous_btn
            @pagination_nav += "<li class='inactive'>Previous</li>"
        end
       
        for @i in @start_loop..@end_loop do
            if @cur_page == @i
                @pagination_nav += "<li class = 'selected'>#{@i}</li>"
            else
                @pagination_nav += "<li class='active'><a href = '#{@current_page_url}?pageno=#{@i}'>#{@i}</a></li>"
            end
        end

        if @next_btn && @cur_page < @no_of_paginations
            @nex = @cur_page + 1
            @pagination_nav += "<li class='active'><a href = '#{@current_page_url}?pageno=#{@nex}'>Next</a></li>"
        elsif @next_btn
            @pagination_nav += "<li class='inactive'>Next</li>"
        end

        if @last_btn && @cur_page < @no_of_paginations
            @pagination_nav += "<li class='active'><a href = '#{@current_page_url}?pageno=#{@no_of_paginations}'>Last</a></li>"
        elsif @last_btn
            @pagination_nav += "<li class='inactive'>Last</li>"
        end

        @pagination_nav = "#{@pagination_nav}
                </ul>
            </div>"

       
        @output = "
            <div>#{@pagination_content}</div>
            <div>#{@pagination_nav}</div>
        "

    end                          
end

On your view/articles/index.html.erb file, we simply output the pagination by calling the @output variable:

1
<%= raw(@output) %>

Here’s a neat CSS code that you can use to style your navigation:

1
2
3
4
5
6
7
8
.pagination-container  { margin-top: 15px; }
.pagination-container ul { margin: 0; padding: 0; }
.pagination-container ul li { display: inline; background: #FFF; color: black; }
.pagination-container ul li.active a:hover { background: #1E8CBE; color: white; text-decoration: none; }
.pagination-container ul li.inactive { background: #d0d0d0; }
.pagination-container ul li.selected { background: #1E8CBE; color: white; }
.pagination-container ul li a { color: #1e8cbe; }
.pagination-container ul li a, .pagination-container ul li.inactive, .pagination-container ul li.selected { margin: 3px; padding: 4px 8px; }

 

The output

Here’s how it will look like when you refresh your page:
 
ruby-on-rails-pagination



Do you need help with a project? or have a new project in mind that you need help with?

Contact Me