Pagination using Kaminari gem
By: Lukasz Muzyka, On:
This tutorial appears in more than one path.
When we work with just couple of records, it's easy to simply list them all on the index page. But, what happens when we have more than two, let's say 100 records? What if we have 1000? How about 1 million? If we try to list all records from the database on a website at once, not only it will be a lot of load on the database, download will take much longer time, but it's likely that user's browser will crash.
Fortunately, there is a way to chop the data in more managable chunks and use separate pages to display the records. This process is called pagination.
To manage this process, we will use gem called "kaminari."
Step 1: Add Kaminari and Bundle Gems
First, add kaminari
to the Gemfile
Gemfile
gem 'kaminari'
gem 'kaminari-bootstrap'
Because we're using bootstrap, we added kaminari-bootstrap
so our page selector are nicely styled.
bash
$ bundle install
We can now instruct our controller to paginate our indexed items. Depending on where in your path you're working with this tutorial, this will concern either posts, connections or users. Code for most part will be identical. The only difference will be different variable name.
Step 2: Working with Posts
If you are working with posts, go to posts_controller.rb
and replace line with new code:
app/controllers/posts_controller.rb
def index
# @posts = Post.all we will replace this old code - you can delete this line
@posts = Post.order('created_at DESC').page(params[:page]).per(15)
end
Step 3: Working with Users
If you are working with users, go to users_controller.rb
and replace line with new code:
app/controllers/users_controller.rb
def index
# @users = User.all we will replace this old code - you can delete this line
@users = User.page(params[:page]).per(30)
end
Step 4: Working with Relationships
If you are working with relationships, go back to users_controller.rb
and add the following lines of code:
app/controllers/users_controller.rb
def index
# @sent_invites = current_user.sent_invites YOU CAN DELETE THIS LINE
# @received_invites = current_user.received_invites YOU CAN DELETE THIS LINE
@sent_invites = current_user.sent_invites.page(params[:page])
@received_invites = current_user.received_invites.page(params[:page])
end
Step 5: Add Navigation Buttons
Now, we can add our navigation buttons to views:
If you're working with posts:
app/views/posts/index.html.erb<
<%= link_to 'New Post', new_post_path %>
<div>
<%= paginate(@posts) %>
<ul>
<% @posts.each do |p| %>
<li>
<h3><%= link_to p.title, post_path(p.id) %></h3>
<p><small><strong>By:</strong> <%= p.user.email %></small></p>
<p><%= p.body %></p>
</li>
<% end %>
</ul>
<%= paginate(@posts) %>
</div>
If you're working with users:
app/views/users/index.html.erb
<div class="container">
<div class="users row">
<%= paginate(@users) %>
<% @users.each do |user| %>
<div class="panel panel-default">
<%= link_to user_path(user) do %>
<div class="panel-body">
<%= image_tag(user.avatar.url(:medium)) %>
<p><%= user.full_name %></p>
</div>
<% end %>
</div>
<% end %>
<%= paginate(@users) %>
</div>
</div>
You can see how easy this is when using a tool like kaminari. All it takes is to declare use in the controller and use <%= paginate(@list_of_something) %>
where you want to display navigation links. If you don't have enough records to display them, go ahead and play with .per()
option. Simply specify how big or small you want the chunks of data to display. The final result should look somehow like this:
Comments
Comment
You can login to comment
On: nate wrote:
Really learned a lot from these. Hope to see more. Thank you!
On: nate wrote:
Really learned a lot from these. Hope to see more. Thank you!