Sử dụng gem Ransack để search trong rails
Bài đăng này đã không được cập nhật trong 6 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
 
  
 