Đánh số thứ tự (index) cho bản ghi kết hợp với phân trang trong ruby on rails
Xin chào các bạn, hôm nay mình sẽ giới thiệu cho các bạn một kỹ thuật đó là đánh số thứ tự (index) trong một danh sách bản ghi khi kết hợp với phân trang. Đây là kỹ thuật tuy đơn giản, nhưng đối với những bạn mới làm quen với ngôn ngữ ruby thì chắc còn gặp phải một chút khó khăn. Đầu tiên chúng ...
Xin chào các bạn, hôm nay mình sẽ giới thiệu cho các bạn một kỹ thuật đó là đánh số thứ tự (index) trong một danh sách bản ghi khi kết hợp với phân trang. Đây là kỹ thuật tuy đơn giản, nhưng đối với những bạn mới làm quen với ngôn ngữ ruby thì chắc còn gặp phải một chút khó khăn.
Đầu tiên chúng ta thêm gem phân trang trong Gemfile
gem "bootstrap-will_paginate", "1.0.0"
vào sau đó
rails bundle install
Mình sẽ tạo ra một model User với các trường name, age, email và address, sau đó chạy migrate
rails g model User name:string age:integer email:string address:string rails db:migrate
Bây giờ chúng ta sẽ tạo dữ liệu để đổ vào model vừa tạo ra bằng cách thêm trong file seeds.rb ở folder db. Ở đây mình thêm 20 bản ghi như sau.
puts "Create user" 20.times do |n| User.create( name: "Nguyễn Văn A #{n+1}", age: 18, email: "email#{n+1}@gmail.com", address: "Ha Noi" ) end
Sau đó chạy lệnnh này
rails db:seed
Tiếp theo mình sẽ tạo controller cho User, các bạn chú ý Users phải là số nhiều nhé
rails g controller Users index
Mở users_controller.rb trong thư mục controllers và sửa thành như sau:
class UsersController < ApplicationController def index @users =User.page(params[:page]).per_page 10 end end
Trong đoạn code trên mình phân trang để hiển thị 10 users trên một trang. Các bạn có thể thay đổi số lượng users muốn hiển thị trên một trang bằng cách sửa lại sô 10 ở trên.
Bạn tìm đếnfile index.html.erb trong views/users và thêm code sau:
<h1 class="text-center" style="color: red;">Users list</h1> <div class="col-md-10 col-lg-offset-1"> <table class="table text-center" style="border: 2px solid black;"> <tr class="bg-primary"> <th class="text-center col-md-1">index</th> <th class="text-center col-md-3">name</th> <th class="text-center col-md-2">Age</th> <th class="text-center col-md-3">Email</th> <th class="text-center col-md-3">Address</th> </tr> <% @users.each_with_index do |user, index| %> <tr class="bg-success"> <td><%= index %></td> <td scope="row"><%= user.name %></td> <td scope="row"><%= user.age %></td> <td scope="row"><%= user.email %></td> <td scope="row"><%= user.address %></td> </tr> <% end %> </table> <%= will_paginate @users %> </div>
Các bạn chú ý mình sử dụng each_with_index thay cho each như bình thường là để lấy thêm index của vòng lặp
Chúng ta gọi thêm hàm helper will_paginate với tham số là @users để tạo các thẻ <a> dẫn tới từng trang cụ thể.
Các bạn có thể thấy như ở đây
Như các bạn đã thấy, chỉ số ở cột index chính là nhờ each_with_index đó. Nhưng nó lại gặp một vấn đề đó là khi mình chuyển sang trang 2 thì cột index vẫn lại bắt đầu từ 0. Vậy làm thế nào để index tiếp tục tăng theo các trang trước???
Để xử lý trường hợp này ta làm như sau
Đầu tiên trong file users_helper.rb ta thêm code sau
module UsersHelper def create_index params_page, index, per_page params_page = 1 if params_page.nil? (params_page.to_i - 1) * per_page.to_i + index.to_i + 1 end end
Ở đây params_page chính là params[:page] là số trang hiện tại. nó được hiển thị ở thanh url “http://localhost:3000/users/index?page=2” ở đây params_page = 2.
Còn số per_page là số lượng users hiển thị trên 1 trang mà mình đã cài đặt ở phần cài đặt trong users_constroller.rb là bằng 10
và index là chỉ số được lấy từ each_with_index trong file index.html.erb
Trong trường hợp params_page = nil như hình 1 đó, thì mình gán cho nó bằng 1 sau đó sử dụng công thức như trên.
Tiếp theo mình sẽ gọi hàm create_index và truyền tham số tương ứng ở file index.html.erb như sau
<h1 class="text-center" style="color: red;">Users list</h1> <div class="col-md-10 col-lg-offset-1"> <table class="table text-center" style="border: 2px solid black;"> <tr class="bg-primary"> <th class="text-center col-md-1">index</th> <th class="text-center col-md-3">name</th> <th class="text-center col-md-2">Age</th> <th class="text-center col-md-3">Email</th> <th class="text-center col-md-3">Address</th> </tr> <% @users.each_with_index do |user, index| %> <tr class="bg-success"> <td><%= create_index params[:page], index, 10 %></td> <td scope="row"><%= user.name %></td> <td scope="row"><%= user.age %></td> <td scope="row"><%= user.email %></td> <td scope="row"><%= user.address %></td> </tr> <% end %> </table> <%= will_paginate @users %> </div>
Và đây là kết quả Vậy là xong rồi đó, chúc các bạn thành công!