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

Tổng quan

Chúng ta có một số bất cập khi tự create 1 method search cho App rails. Vậy muốn xử lý search được đơn giản và kết hợp được nhiều điều kiện searcg ta nên dùng gem ransack. Bài viết này mình sẽ nói về cách dùng gem "ransack" để search.

Cài đặt

gem "ransack"

Cách dùng

  1. Ở Controller:
def index
    @q = Product.ransack(params[:q])
    @products = @q.result.page(params[:page])
end
  1. Ở View:
<%= search_form_for @q do |f| %>
  # Tìm kiếm với name like %abc%
  <%= f.label :name_cont %>
  <%= f.search_field :name_cont %>

  # Tìm kiếm nhiều field like %abc%
  <%= f.label :name_or_description_or_content_cont %>
  <%= f.search_field :name_or_description_or_content_cont %>

  <%= f.submit %>
<% end %>

Các option

Ở đây ransack sử dụng các vị ngữ để tìm kiếm. Các vị ngữ được sử dụng trong các truy vấn để tìm kiếm gồm:

  • eq (equals). Trả về tất cả các bản ghi có giá trị của trường chính xác bằng một giá trị cho trước.
Product.ransack(name_eq: "Mobile").result.to_sql
=> SELECT "products".* FROM "products" WHERE "products"."name" = 'Mobile'
  • not_eq (Not equals) ngược lại của eq
  • matches. Trả về tất cả các bản ghi có giá trị của trường như giá trị cho trước.
Product.ransack(name_matches: "Mobile").result.to_sql
=> SELECT "products".* FROM "products" WHERE "products"."name" LIKE 'Mobile'
  • does_not_match. Ngược lại matches.
  • lt (less than). Trả về tất cả các bản ghi có giá trị của trường nhỏ hơn giá trị cho trước.
Product.ransack(price_lt: 25).result.to_sql
=> SELECT "products".* FROM "products" WHERE ("products"."price" < 25)
  • gteq (greater than or equal to). Trả về tất cả các bản ghi có giá trị của trường lớn hơn hoặc bằng giá trị cho trước.
Product.ransack(price_gteq: 25).result.to_sql
=> SELECT "products".* FROM "products" WHERE ("products"."price" >= 25)
  • lteq (less than or equal to). Trả về tất cả các bản ghi có giá trị của trường nhỏ hơn hoặc bằng giá trị cho trước.
Product.ransack(price_lteq: 25).result.to_sql
=> SELECT "products".* FROM "products" WHERE ("products"."price" <= 25)
  • gt (greater than). Trả về tất cả các bản ghi có giá trị của trường lớn hơn giá trị cho trước.
Product.ransack(price_gt: 25).result.to_sql
=> SELECT "products".* FROM "products" WHERE ("products"."price" > 25)
  • in. Trả về tất cả các bản ghi có giá trị của trường nằm trong danh sách được cho trước.
Product.ransack(price_in: 20..25).result.to_sql
=> SELECT "products".* FROM "products" WHERE "products"."price" IN (20, 21, 22, 23, 24, 25)
  • not_in. Ngược lại của in.
  • cont. Trả về tất cả các bản ghi có giá trị của trường chứa giá trị được cho trước.
Product.ransack(name_cont: "Mobile").result.to_sql
=> SELECT "products".* FROM "products" WHERE ("products"."name" LIKE '%Mobile%')
  • not_cont. Ngược lại của cont.
  • cont_any (contains any). Trả về tất cả các bản ghi có giá trị của trường chứa bất kỳ giá trị nào.
Product.ransack(name_cont_any: %w(Mobile Laptop)).result.to_sql
=> SELECT "products".* FROM "products"  WHERE (("products"."name" LIKE '%Mobile%' OR "products"."name" LIKE '%Laptop%'))
  • not_cont_any. Ngược lại của cont_any
  • cont_all (contains all). Trả về tất cả các bản ghi có giá trị của trường chứa tất cả giá trị cho trước.
Product.ransack(name_cont_all: %w(Mobile Laptop)).result.to_sql
=> SELECT "products".* FROM "products"  WHERE (("products"."name" LIKE '%Mobile%' AND "products"."name" LIKE '%Laptop%'))
  • not_cont_all. Ngược lại của cont_all
  • start (starts with). Trả về tất cả các bản ghi có giá trị của trường bắt đầu bằng giá trị cho trước.
Product.ransack(name_start: "Mobile").result.to_sql
=> SELECT "products".* FROM "products" WHERE "products"."name" LIKE 'Mobile%'
  • not_start. Ngược lại của start
  • end (ends with). Trả về tất cả các bản ghi có giá trị của trường kết thúc bằng giá trị cho trước.
Product.ransack(name_end: "Mobile").result.to_sql
=> SELECT "products".* FROM "products" WHERE "products"."name" LIKE '%Mobile'
  • not_end. Ngược lại của end
  • true. Trả về tất cả các bản ghi có giá trị của trường là true.
User.ransack(activated_true: '1').result.to_sql
=> SELECT "users".* FROM "users"  WHERE ("users"."activated" = 't')
  • not_true. Ngược lại của true.
  • false. Trả về tất cả các bản ghi có giá trị của trường là false.
User.ransack(activated_false: '1').result.to_sql
=> SELECT "users".* FROM "users"  WHERE ("users"."activated" = 'f')
  • not_false. Ngược lại của false.
  • present. Trả về tất cả các bản ghi có giá trị của trường không phải null và không phải là một chuỗi trống.
 Product.ransack(name_present: '1').result.to_sql
=> SELECT "products".* FROM "products"  WHERE (("products"."name" IS NOT NULL AND "products"."name" != ''))
  • blank. Ngược lại của present.
  • null. Trả về tất cả các bản ghi có giá trị của trường là null.
Product.ransack(name_null: 1).result.to_sql
=> "SELECT `products`.* FROM `products` WHERE `products`.`name` IS NULL"
  • not_null. Ngược lại của null

Tài liệu tham khảo: