Phân trang trong Rails sử dụng Gem Kaminari và tạo select limit load với gem Ransack
Bài đăng này đã không được cập nhật trong 3 năm
1.Giới thiệu
Phân trang là một kĩ thuật rất phổ biến và quan trọng trong các trang web lớn,khi mà số lượng các item nhiều. Đó là yếu tố sống còn của website khi mà nó trực tiếp ảnh hưởng đến hiệu năng của hệ thống. Tôi lấy một ví dụ đơn gian nếu chúng ta cần phải load ra 100000 bản ghi tốn mất khoảng 3s thì với 1 triệu bản ghi sẽ mất khoảng 30s. Điều đó là không thể chấp nhận được khi bắt người dùng chờ đến 30s/1 request.Hơn nữa việc load ra tất cả các bản ghi 1 lúc là không cần thiết khi mà người dùng không thể xem hết một lúc 1 triệu bản ghi được. Hôm nay tôi sẽ hướng dẫn các bạn sử dụng gem kaminari trong Rails để phân trang cho list item của bạn. Cộng với một phần ứng dụng Gem tìm kiếm Ransack để tạo form slect số lượng item bạn muốn load trên một trang.
Chém gio thế chắc cũng đủ rồi.Chúng ta bắt đầu nào!
2.Các bước thực hiện
2.1. Khởi tạo một project mới với Rails và thêm các Gem cần thiết vào
rails new kaminari_demo
Trong file Gemfile chúng ta thêm các Gem sau
gem 'kaminari' // gíup phân trang
gem 'ransack' // tạo form tìm kiếm
gem 'bootstrap-kaminari-views' // giao diện đẹp cho phân trang
2.2. Tạo một trang Product, tạo cơ sở dữ liệu mẫu và viết view + controller
Tạo model Product
rails generate model Product
viết view và controller
Tạo file app/controllers/products_controller.rb
class ProductsController < ApplicationController
def index
@products = Product.all
end
end
Trong file app/views/product.html.erb
<h1>ALL PRODUCT</h1>
<%- @products.each do |product| %>
<%= product.title %>
</br>
<% end %>
Trong file config/routes.rb
Rails.application.routes.draw do
resources :products
end
Fake dữ liệu nữa chúng ta sẽ được một trang Products như thế này
2.3. Phân trang
Chúng ta viết trong file app/controllers/products_controller.rb
def index
@products = Product.all.page params[:page]
end
Trong file app/views/product.html.erb
<%- @products.each do |product| %>
<%= product.title %>
</br>
<% end %>
<%= paginate @products %>
Chúng ta sẽ thu được một trang Product đã được phân trang như sau.
Như vậy là chúng ta đã tạo thành công một trang products sử dụng Gem kaminari để phân trang.
2.4 Config Gem Kaminari và chỉnh giao diện
- Giới hạn số lượng Item
Chúng ta có thể giới hạn số lượng item load ra trên một trang như sau.trong file app/controllers/products_controller.rb
def index
@products = Product.all.page(params[:page]).per(5)
end
chúng ta sẽ thu được như sau.
- Config các thông số khác
Ngoài ra chúng ta có thể generate ra file config bằng lệnh
% rails g kaminari:config
Sẽ tạo ra file config/initializers/kaminari_config.rb
Kaminari.configure do |config|
# config.default_per_page = 25
# config.max_per_page = nil
# config.window = 4
# config.outer_window = 0
# config.left = 0
# config.right = 0
# config.page_method_name = :page
# config.param_name = :page
end
- Chỉnh lại giao diện đẹp
Để chỉnh lại giao diện đẹp mắt trước tiên chúng ta phải cài Gem bootstrap.Các bạn có thể xam hướng dẫn cài đặt bootstrap tại đây
Trong file app/views/product.html.erb chúng ta thêm theme: 'twitter-bootstrap-3'
<%- @products.each do |product| %>
<%= product.title %>
</br>
<% end %>
<%= paginate @products, theme: 'twitter-bootstrap-3' %>
chúng ta sẽ thu được như hình dưới đây.
- Chỉnh I18n và lable
Kaminari mặc định các I18n và các lable là 'first', 'last', 'previous', '…' and 'next',chúng ta có thể thay đổi các lable này bằng cách override trong file config/locales/en.yml như sau:
en:
hello: "Hello world"
views:
pagination:
first: "« FIRST"
last: "LAST »"
previous: "‹ PREV"
next: "NEXT ›"
truncate: "…"
helpers:
page_entries_info:
one_page:
display_entries:
zero: "No %{entry_name} found"
one: "Displaying <b>1</b> %{entry_name}"
other: "Displaying <b>all %{count}</b> %{entry_name}"
more_pages:
display_entries: "Displaying %{entry_name} <b>%{first} - %{last}</b> of <b>%{total}</b> in total"
chúng ta sẽ thu được giao diện mới như sau:
Bạn thấy các lable đã được viết hoa.
- Tạo friendly URLs
Để tạo một đường dẫn thân thiện giúp cho SEO dễ dàng hơn.chúng ta có thể chỉnh trong file config/routes.rb như sau:
Rails.application.routes.draw do
concern :paginatable do
get '(page/:page)', action: :index, on: :collection, as: ''
end
resources :products, concerns: :paginatable
end
Sẽ tạo thành URLs /products/page/3 instead of /products?page=3
3.Select limit item với Gem ransack
Để tạo được một select form trước tiên chúng ta add thêm gem ransack và gem config vào Gemfile
gem 'ransack'
gme 'config'
Trong file config/settings.yml thêm các lựa chọn vào các settings như sau:
show_limit:
show_5: 5
show_10: 10
show_15: 15
show_20: 20
show_30: 30
show_50: 50
Truyền biến @search từ trong controller ra ngoài view.Ở đây chúng ta phải nhận params[:limit] từ ngoài view truyền vào.
def index
@search = Product.all.ransack params[:q]
@products = @search.result.page(params[:page]).per params[:limit]
end
Sau đó tạo một form search trong html.Đây là form search sử dụng gem ransack. Chúng ta sẽ để ẩn nút submit đi. Chi tiết về gem ransack bạn có thể xem tại đây
<%= search_form_for @search, url: products_path do |f|%>
<%= select_tag :limit, options_from_collection_for_select(Settings.show_limit, :second, :second, selected: params[:limit] || Settings.show_limit.limit),id: "show-limit"%>
<%= f.submit "search", class: "btn btn-info", style: "display: none; margin-right: 10px"%>
<% end %>
Cuối cùng bạn cần phải viết một đoạn javascript để nhấn nút submit mỗi khi select changed.bạn có thể viết ngay trong app/assets/javascripts/application.js
$(function(){
$("#show-limit").on("change", function(){
$(this).closest("form").trigger("submit");
});
})
Đến đây chúng ta sẽ thu được một form select limit load như thế này.
Bạn chọn 20 và form sẽ load ra 20 products. Như vậy là tôi đã hướng dẫn xong toàn bộ cách phân trang cho trang web trong Rails sử dụng Gem Kaminari và tạo select limit load với gem Ransack.Chúc các bạn thực hiện thành công và có những ứng dụng hay vào trong trang web của mình!
4.Tài liệu tham khảo
https://github.com/railsconfig/config https://github.com/activerecord-hackery/ransack https://github.com/amatsuda/kaminari
Tất cả source code của project demo các bạn có thể lấy về ở đây
-- Hoàng Văn Trình AS Việt Nhật K55 Đại học Bách Khoa Hà Nội
All rights reserved