Tìm hiểu Gem Ransack
Bài đăng này đã không được cập nhật trong 3 năm
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ụngUser.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àmresult
.
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> <!-- Tìm kiếm theo name có chứa ... -->
<div class="form-group">
<%= f.label :age_gteq, 'Age >= ' %>
<%= f.text_field :age_gteq, class: "form-control" %><br>
</div> <!-- Tìm kiếm theo age lớn hơn bằng ... -->
<%= 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ằngVD:
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ớieq
-
lt(less than)
: ít hơnVD:
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ớilt
-
lteq (less than or equal to)
: ít hơn hoặc bằngVD:
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ớilteq
-
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ớiin
-
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ớicont
-
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ớiend
-
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ớistart
...
- 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ằngPOST
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.
Tài liệu tham khảo:
All rights reserved