Tìm hiểu Gem Ransack
Bài đăng này đã không được cập nhật trong 4 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.rbta sử dụngUser.searchvớ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_forthay 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
sortcá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
GETrequest bị giới hạn ta có thể thay thế bằngPOSTrequest:
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