Tìm hiểu Gem Ransack
I. Ransack là gì? Ransack là 1 gem trong Ruby on the Rails giúp hỗ trợ người dùng xây dựng các tìm kiếm. Ransack cho phép tìm kiếm với hai hình thức đơn giản và nâng cao tùy theo các mô hình ứng dụng trong chương trình. Ngoài ra, nó còn giúp sắp xếp kết quả tìm kiếm được theo mục đích của ...
I. Ransack là gì?
- Ransack là 1 gem trong Ruby on the Rails giúp hỗ trợ người dùng xây dựng các tìm kiếm.
- Ransack cho phép tìm kiếm với hai hình thức đơn giản và nâng cao tùy theo các mô hình ứng dụng trong chương trình.
- Ngoài ra, nó còn giúp sắp xếp kết quả tìm kiếm được theo mục đích của người sử dụng.
II. Cài đặt
Thêm gem ransack vào Gemfile, sau đó bundle.
gem 'ransack'
III. Ví dụ
-
Áp dụng với dữ liệu mẫu User với các trường: name, age
-
Để tìm kiếm các users thì sau khi cài đặt gem ransack xong, trong user_controller.rb ta sử dụng User.search với param mặc định là params[:q], với tham số q là một hash gồm các trường của User và cách tìm kiếm trường đó. Để lấy kết quả tìm kiếm ta sử dụng hàm result.
class UsersController < ApplicationController def index @search = User.search(params[:q]) @users = @search.result end end
- Trong view Ransack sử dụng search_form_for thay vì form_for bình thường để tạo form search cho @search:
<%= search_form_for @search, class: "form-inline" do |f| %> <div class="form-group"> <%= f.label :name_cont, 'User Name:' %> <%= f.text_field :name_cont, class: "form-control" %><br> </div> <div class="form-group"> <%= f.label :age_gteq, 'Age >= ' %> <%= f.text_field :age_gteq, class: "form-control" %><br> </div> <%= f.submit 'Search', class: "btn btn-default" %> <% end %>
_Tìm kiếm các user có name chứa "Nguyen" _
_... và age lớn hơn bằng 25 _
Ta cũng có thể tìm kiếm nhiều trường một lúc:
<div class="form-group"> <%= f.label :name_or_nick_name_cont, 'Name or Nick Name:' %> <%= f.text_field :name_or_nick_name_cont, class: "form-control" %><br> </div>
- Một số quy tắc search:
-
eq (equals): bằng
VD:
User.ransack(name_eq: 'Hang').result.to_sql => SELECT "users".* FROM "users" WHERE "users"."name" = 'Hang'
-
not_eq: không bằng, ngược lại với eq
-
lt(less than): ít hơn
VD:
User.ransack(age_lt: 25).result.to_sql => SELECT "users".* FROM "users" WHERE ("users"."age" < 25)
-
gt(greater than): lớn hơn, ngược lại với lt
-
lteq (less than or equal to): ít hơn hoặc bằng
VD:
User.ransack(age_lteq: 25).result.to_sql => SELECT "users".* FROM "users" WHERE ("users"."age" <= 25)
-
gteq (greater than or equal to) : lớn hơn hoặc bằng, ngược lại với lteq
-
in: nằm trong ...
VD:
User.ransack(age_in: 20..22).result.to_sql => SELECT "users".* FROM "users" WHERE "users"."age" IN (20, 21, 22)
-
not_in: không nằm trong..., ngược lại với in
-
cont: chứa ...
VD:
User.ransack(nick_name_cont: 'Hon').result.to_sql => SELECT "users".* FROM "users" WHERE ("users"."nick_name" LIKE '%Hon%')
-
not_cont: không chứa..., ngược lại với cont
-
end (ends with): kết thúc bằng...
VD:
User.ransack(nick_name_end: 'Hon').result.to_sql => SELECT "users".* FROM "users" WHERE ("users"."nick_name" LIKE '%Hon')
-
not_end: không kết thúc bằng..., ngược lại với end
-
start (starts with): bắt đầu bằng...
VD:
User.ransack(nick_name_start: 'Hon').result.to_sql => SELECT "users".* FROM "users" WHERE ("users"."nick_name" LIKE 'Hon%')
-
not_start: không bắt đầu bằng..., ngược lại với start
...
- Ransack cung cấp cách sort các kết quả search được theo link:
Trong view index.html.erb:
<tr> <th><%= sort_link(@search, :name, 'User Name') %></th> <th><%= sort_link(@search, :age, 'Age') %></th> </tr>
Khi tải lại trang sẽ có các liên kết để phân loại các bảng kết quả theo từng trường.
Sắp xếp age theo thứ tự giảm dần
- Ransack hỗ trợ tự động tìm kiếm theo nhu cầu: tự chọn trường, cách thức tìm kiếm, giá trị:
Trong user_controller.rb thêm:
... @search.build_condition
Trong view index.html.erb sử dụng condition_fields method:
<%= search_form_for @search, class: "form-inline" do |f| %> <%= f.condition_fields do |c| %> <%= c.attribute_fields do |a| %> <%= a.attribute_select %> <% end %> <%= c.predicate_select %> <%= c.value_fields do |v| %> <%= v.text_field :value %> <% end %> <% end %> <%= f.submit 'Search', class: "btn btn-default" %> <% end %> <% end %>
- Tương tự như vậy, ransack cũng áp dụng tùy chọn với sort:
Trong user_controller.rb thêm:
... @search.build_sort
Trong view index.html.erb sử dụng sort_fields method:
<%= f.sort_fields do |s| %> <%= s.sort_select %> <% end %>
Minh họa
- Ngoài ra nếu truyền quá nhiều dữ liệu tìm kiếm mà trên GET request bị giới hạn ta có thể thay thế bằng POST request:
Trong config/routes.rb
Rails.application.routes.draw do root to: 'users#index' resources :users do collection { post :search, to: 'users#index' } end end
search_form_for:
<%= search_form_for @search, url: search_users_path, method: :post do |f| %> ... <% end %>
Kết luận: Ransack thực sự là một công cụ hỗ trợ tìm kiếm đơn giản và dễ dàng trong thư viện gem của Ruby on the Rails.