0
0
Lập trình
TT

[Rails] Bộ lọc truy vấn tiện lợi cho sản phẩm

Đăng vào 1 tháng trước

• 2 phút đọc

Mọi người đều biết đến Active Record, một công cụ cho phép chúng ta viết các truy vấn dễ hiểu và có thể tái sử dụng. Hãy xem xét ví dụ sau với các mô hình liên quan đến sản phẩm và cửa hàng.

Mô tả các mô hình

  • Cửa hàng (Shop): Lưu trữ thông tin về các cửa hàng nơi sản phẩm được bán.
  • Sản phẩm (Product): Chứa thông tin chi tiết về sản phẩm, bao gồm giá tối đa, giá tối thiểu, tên, thương hiệu, danh mục và của hàng.

Yêu cầu hiển thị sản phẩm

Chúng ta cần xây dựng một trang web để hiển thị danh sách sản phẩm và có thể thêm một số bộ lọc như sau:

  • Theo shop_id: chỉ hiển thị các sản phẩm thuộc một cửa hàng cụ thể.
  • Theo tên sản phẩm: nhập một chuỗi để tìm kiếm sản phẩm có chứa chuỗi đó.
  • Theo giá: chọn sản phẩm có giá lớn hơn 100 đô la hoặc nhỏ hơn 150 đô la.
  • Theo brand_id: lọc sản phẩm theo thương hiệu.
  • Theo category_id: lọc sản phẩm theo danh mục.

Ví dụ về truy vấn

Khi muốn lọc các sản phẩm, có thể sử dụng các câu lệnh sau:

ruby Copy
query = Product.all
query = query.where(shop_id: params[:shop_id]) if params[:shop_id]
query = query.where("name LIKE ?", "%#{params[:name]}%") if params[:name]
query = query.where("min_price >= ?", params[:price_from]) if params[:price_from]
query = query.where("max_price <= ?", params[:price_to]) if params[:price_to]
query = query.where(brand_id: params[:brand_id]) if params[:brand_id]
query = query.where(category_id: params[:category_id]) if params[:category_id]

Tối ưu hóa truy vấn với lớp xây dựng

Phương pháp trên có thể giải quyết yêu cầu của chúng ta, nhưng trong thực tế, có thể có nhiều điều kiện và logic phức tạp hơn. Do đó, một lớp xây dựng truy vấn (Query Builder) có thể nhận một hash đầu vào và trả về kết quả mong muốn là một giải pháp hợp lý hơn. Dưới đây là cách xây dựng một lớp truy vấn cho sản phẩm:

ruby Copy
class ProductQueryBuilder
  attr_reader :params
  FILTERS = %i(store_id brand_id category_id name from_price to_price)

  def initialize(params = {})
    @params = params
  end

  def exec
    query = Product.all
    FILTERS.each do |key|
      next unless params[key]
      query = query.where(send("#{key}_filter"), params[key])
    end

    query
  end

  def store_id_filter(store_id)
    Product.arel_table[:store_id].eq(store_id)
  end

  def brand_id_filter(brand_id)
    Product.arel_table[:brand_id].eq(brand_id)
  end

  def category_id_filter(category_id)
    Product.arel_table[:category_id].eq(category_id)
  end

  def name_filter(name)
    Product.arel_table[:name].matches("%#{sanitize_sql_like(name)}%")
  end

  def from_price_filter(price)
    Product.arel_table[:min_price].gteq(price)
  end

  def to_price_filter(price)
    Product.arel_table[:max_price].lteq(price)
  end
end

Lời kết

Giờ đây, khi muốn sử dụng lớp ProductQueryBuilder, chúng ta chỉ cần làm như sau:

ruby Copy
params = {store_id: 1, brand_id: 3, category_id: nil}
ProductQueryBuilder.new(params).exec

Điều này giúp giảm thiểu mã nguồn và cải thiện khả năng bảo trì của ứng dụng. Bằng cách sử dụng lớp này, chúng ta có thể dễ dàng áp dụng các bộ lọc và xây dựng các truy vấn phức tạp hơn mà không cần phải viết nhiều câu lệnh where mỗi lần.

Hy vọng rằng với bộ lọc truy vấn tiện lợi này, bạn sẽ có thể xây dựng các ứng dụng Rails mạnh mẽ hơn!
source: viblo

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào