+1

Sử dụng gem Ransack để search trong rails

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_nameemail, 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

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí