Sử dụng gem Ransack để search trong rails
Bài đăng này đã không được cập nhật trong 5 năm
Giới thiệu
Mình xin giới thiệu về cách search bằng gem Ransack qua quá trình mà mình đã áp dụng vào project của bản thân và 1 số options được sử dụng
Sử dụng gem trong project
Đầu tiên ta thêm gem Ransack vào Gemfile:
gem "ransack"
Sau đó chạy
bundle install
Ở đây mình có dữ liệu của 1 model user với các trường name, email, address,...
Sau khi cài đặt xong gem, ta vào model của User thêm scope
scope :search_user, lambda{|search|
search&.squish! if search
ransack(user_name_or_email_cont: search).result
}
Tiếp theo ở Controller User ta có phương thức Index và search_params:
def index
params = search_params ? search_params[:user_name_or_email] : nil
@users = User.search_user(params).page(params[:page]).per 5
end
def search_params
return nil unless params[:user_list]
params.require(:user_list).permit :user_name_or_email
end
Ở đây ta search theo user_name và email, trên Index hiển thị 5 bản ghi trên 1 trang.
Tiếp theo ở views/users/index.html.erb ta thêm:
<%= form_tag users_path, method: :get do |f| %>
<%= text_field_tag :user_name_or_email, nil,
class: "form__control has-icon list-user__search",
name: "user_list[user_name_or_email]",
value: value_search(params[:user_list], :user_name_or_email),
placeholder: t("search.name_email") %>
<%= button_tag :submit, class: "form__search-btn" do %>
<span class="icon-search-left"></span>
<% end %>
<% end %>
Như vậy ta có thể search user qua user_name và email.
Các option
- eq(equals): Trả về kết quả gồm tất cả bản ghi có giá trị chính xác bằng giá trị đã cho:
pry(main)> User.ransack(user_name_eq: 'Lam').result.to_sql
=> "SELECT `users`.* FROM `users` WHERE `users`.`user_name` = 'Lam'"
Ngược lại: not_eq
pry(main)> User.ransack(user_name_not_eq: 'Lam').result.to_sql
=> "SELECT `users`.* FROM `users` WHERE `users`.`user_name` != 'Lam'"
- matches: Trả về kết quả gồm các bản ghi có giá trị giống với giá trị đã cho:
pry(main)> User.ransack(user_name_matches: 'Lam').result.to_sql
(0.7ms) SET NAMES utf8, @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'),
',NO_AUTO_VALUE_ON_ZERO'), @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
=> "SELECT `users`.* FROM `users` WHERE `users`.`user_name` LIKE 'Lam'"
Ngược lại: does_not_match
pry(main)> User.ransack(user_name_does_not_match: 'Lam').result.to_sql
=> "SELECT `users`.* FROM `users` WHERE `users`.`user_name` NOT LIKE 'Lam'"
- It(less than): Trả về kết quả gồm các bản ghi có giá trị nhỏ hơn giá trị đã cho:
pry(main)> User.ransack(age_lt: 25).result.to_sql
=> "SELECT `users`.* FROM `users` WHERE `users`.`age` < 25"
Ngược lại: gteq (greater than or equal to)
pry(main)> User.ransack(age_gteq: 25).result.to_sql
=> "SELECT `users`.* FROM `users` WHERE `users`.`age` >= 25"
- in: Trả về kết quá gồm các bản ghi có giá trị nằm trong khoảng giá trị đã cho:
pry(main)> User.ransack(age_in: 20..25).result.to_sql
=> "SELECT `users`.* FROM `users` WHERE `users`.`age` IN (20, 21, 22, 23, 24, 25)"
Ngược lại: not_in
pry(main)> User.ransack(age_not_in: 20..25).result.to_sql
=> "SELECT `users`.* FROM `users` WHERE `users`.`age` NOT IN (20, 21, 22, 23, 24, 25)"
- cont: Trả về kết quả gồm các bản ghi có giá trị chứa các giá trị đã cho:
pry(main)> User.ransack(user_name_cont: 'Lam').result.to_sql
=> "SELECT `users`.* FROM `users` WHERE `users`.`user_name` LIKE '%Lam%'"
Ngược lại: not_cont
pry(main)> User.ransack(user_name_not_cont: 'Lam').result.to_sql
=> "SELECT `users`.* FROM `users` WHERE `users`.`user_name` NOT LIKE '%Lam%'"
- cont_all: Trả về kết quả gồm tất cả các bản ghi có chứa giá trị đã cho:
pry(main)> User.ransack(user_name_cont_all: %w(Tung Lam)).result.to_sql
=> "SELECT `users`.* FROM `users` WHERE (`users`.`user_name` LIKE '%Tung%' AND `users`.`user_name` LIKE '%Lam%')"
Ngược lại: not_cont_all
pry(main)> User.ransack(user_name_not_cont_all: %w(Tung Lam)).result.to_sql
=> "SELECT `users`.* FROM `users` WHERE (`users`.`user_name` NOT LIKE '%Tung%' AND `users`.`user_name` NOT LIKE '%Lam%')"
- start: Trả về kết quả gồm các bản ghi có giá trị bắt đầu là các giá trị đã cho:
pry(main)> User.ransack(user_name_start: 'Lam').result.to_sql
=> "SELECT `users`.* FROM `users` WHERE `users`.`user_name` LIKE 'Lam%'"
Ngược lại: not_start
pry(main)> User.ransack(user_name_not_start: 'Lam').result.to_sql
=> "SELECT `users`.* FROM `users` WHERE `users`.`user_name` NOT LIKE 'Lam%'"
- end: Trả về kết quả gồm các bản ghi có giá trị kết thúc là các giá trị đã cho:
pry(main)> User.ransack(user_name_end: 'Lam').result.to_sql
=> "SELECT `users`.* FROM `users` WHERE `users`.`user_name` LIKE '%Lam'"
Ngược lại: not_end
pry(main)> User.ransack(user_name_not_end: 'Lam').result.to_sql
=> "SELECT `users`.* FROM `users` WHERE `users`.`user_name` NOT LIKE '%Lam'"
Và nhiều option khác.
link tham khảo: https://github.com/activerecord-hackery/ransack/wiki/Basic-Searching
All rights reserved