Helpex - Trao đổi & giúp đỡ Đăng nhập
5

Lai lịch:

Tôi có Productmô hình bao gồm 4 loại

class Product < ActiveRecord::Base
  enum category: [:recent, :cheapest, :most_expensive, :popular]
end

Tôi đã triển khai một tùy chỉnh ORDER BYcho từng danh mục với phân trang ( LIMIT 10), vì vậy khi tôi nhận được danh sách sản phẩm, tôi sẽ nhận được nhiều SQLtruy vấn với các truy vấn khác nhau ORDER BYtrong mỗi truy vấn như sau:

gần đây: SELECT "products".* FROM "products" ORDER BY "products"."created_at" DESC LIMIT 10

rẻ nhất:SELECT "products".* FROM "products" ORDER BY "products"."price" ASC LIMIT 10

đắt nhất: SELECT "products".* FROM "products" ORDER BY "products"."price" DESC LIMIT 10

phổ biến: SELECT "products".* FROM "products" ORDER BY "products"."popularity" DESC, "products"."created_at" DESC LIMIT 10

Vì vậy, như đã đề cập, mỗi truy vấn ở trên, kết quả a Product::ActiveRecord_Relationchứa 10 sản phẩm với thứ tự khác nhau cho mỗi truy vấn.

Câu hỏi:

Tôi đã thêm cột mới vào Productmô hình featuredcó giá trị boolean và tôi cần áp dụng ORDER BY featured DESCở đầu mỗi truy vấn với việc giữ nguyên các ORDER BYtrường khác (nghĩa là truy vấn phổ biến phải như thế này SELECT "products".* FROM "products" ORDER BY "products"."featured" DESC, "products"."popularity" DESC, "products"."created_at" DESC LIMIT 10).

Lưu ý: ORDER BY featured DESC chỉ được thêm vào ở đầu ORDER BYcâu lệnh trước và nó được áp dụng trên tập hợp con không phải trên toàn bộ mô hình.

Những gì tôi đã thử?

Tôi đã thử các tình huống sau:

  • Thêm @products = @products.order(featured: :desc)bộ điều khiển vào nhưng kết quả không như mong đợi vì nó thêm đơn hàng vào cuối đơn hàng hiện có theo chuỗi.
  • Sử dụng default_scopetrong mô hình Sản phẩm default_scope { order(featured: :desc) }nhưng kết quả không như mong đợi vì nó thực hiện đơn hàng trên toàn bộ mô hình, nhưng kết quả mong đợi là áp dụng thứ tự chỉ trên tập con (10 bản ghi).
  • sử dụng reordertrong bộ điều khiển @products = @products.reorder('').order(featured: :desc)nhưng kết quả vẫn không như mong đợi vì điều này loại bỏ thứ tự cũ và thực sự tôi cần giữ nó nhưng ở cuối ORDER BYchuỗi

Giải pháp duy nhất tôi có thể làm là sử dụng biến chuỗi để lưu thứ tự trước đó theo chuỗi, sau đó sử dụng reorder('').order(featured: :desc)và cuối cùng nối chuỗi vào cuối new ORDER BY:

current_order = @products.to_sql[@products.to_sql.downcase.index('order by')+8..@products.to_sql.downcase.index('limit')-1]
@products = @products.reorder("featured desc, #{current_order}" )

Nhưng tôi chắc rằng có một giải pháp tốt hơn mà tôi cần sự hỗ trợ của bạn để đạt được nó.

Bản tóm tắt:

Như tóm tắt trong các nhận xét bên dưới, tôi cần triển khai như sau:

Chỉ rở một nơi r = M.order(:a), tôi muốn chạy r.something(:b)và nhận được hiệu quả M.order(:b).order(:a)hơn là những M.order(:a).order(:b)thứ r.order(:b)sẽ mang lại cho bạn

5 hữu ích 4 bình luận 1.3k xem chia sẻ
1

Có lý do gì bạn không sử dụng scopechuỗi ở đây? Đây có vẻ như là một trường hợp hoàn hảo để sử dụng nó. Việc sử dụng enumcũng không rõ ràng.

Một cái gì đó như thế này:

# /app/models/product.rb
class Product < ActiveRecord::Base
 scope :recent, { order(created_at: :desc) }
 scope :cheapest, { order(price: :asc) }
 scope :most_expensive, { order(price: :desc) }
 scope :popular, { order(popularity: :desc) }
 scope :featured, { where(featured: true) }
end

Sau đó, trong bộ điều khiển của bạn, bạn có thể làm:

# /app/controllers/products_controller.rb
...
Product.featured.cheapest.limit(10)
Product.featured.most_expensive.limit(10)
...

và như thế.

AREL nên xây dựng các truy vấn một cách chính xác, và IIRC bạn có thể trao đổi các chuỗi các phạm vi ( featuredsau cheapest, ví dụ) nếu bạn muốn họ được áp dụng khác.

1 hữu ích 2 bình luận chia sẻ
loading
Không tìm thấy câu trả lời bạn tìm kiếm? Duyệt qua các câu hỏi được gắn thẻ ruby-on-rails ruby activerecord sql-order-by rails-activerecord , hoặc hỏi câu hỏi của bạn.

Có thể bạn quan tâm

loading