背景:
我有Product
模型,其中包含4个类别
class Product < ActiveRecord::Base
enum category: [:recent, :cheapest, :most_expensive, :popular]
end
我已为每个分页(ORDER BY
)实施了自定义LIMIT 10
,因此,当我获得产品列表时,我会获得多个{{1在每个查询中使用不同SQL
的查询,如下所示:
最近:
ORDER BY
便宜的: SELECT "products".* FROM "products" ORDER BY "products"."created_at" DESC LIMIT 10
most_expensive: SELECT "products".* FROM "products" ORDER BY "products"."price" ASC LIMIT 10
热门: SELECT "products".* FROM "products" ORDER BY "products"."price" DESC LIMIT 10
如上所述,上述每个查询结果SELECT "products".* FROM "products" ORDER BY "products"."popularity" DESC, "products"."created_at" DESC LIMIT 10
包含10个产品,每个查询的订单顺序不同。
问题:
我已经为Product::ActiveRecord_Relation
模型添加了新列,其中Product
具有布尔值,我需要在每个查询的开头应用featured
并保留另一个{ {1}}字段不变(即热门查询应该像ORDER BY featured DESC
)。
注意: ORDER BY
仅附加在上一个SELECT "products".* FROM "products" ORDER BY "products"."featured" DESC, "products"."popularity" DESC, "products"."created_at" DESC LIMIT 10
语句的开头,并且它应用于不在整个模型上的子集。
我尝试了什么?
我尝试了以下方案:
ORDER BY featured DESC
但结果不符合预期,因为它会按顺序将订单添加到现有订单的末尾。ORDER BY
中使用@products = @products.order(featured: :desc)
但结果不符合预期,因为它实现了整个模型的订单,但预期结果仅在子集上应用订单(10条记录) default_scope
中使用default_scope { order(featured: :desc) }
,但结果仍然不符合预期,因为这会删除旧订单,实际上我需要保留它,但是在reorder
链的末尾我能够做的唯一解决方案是使用字符串变量按链保存先前的顺序,然后使用@products = @products.reorder('').order(featured: :desc)
并最后在新ORDER BY
的末尾附加字符串:< / p>
reorder('').order(featured: :desc)
但我确信有更好的解决方案需要您的支持才能实现。
答案 0 :(得分:1)
你有没有在这里使用scope
链接的原因?这似乎是一个使用它的完美案例。enum
的使用也不清楚。
这样的事情:
# /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
然后在你的控制器中你可以做到:
# /app/controllers/products_controller.rb
...
Product.featured.cheapest.limit(10)
Product.featured.most_expensive.limit(10)
...
等等。
AREL应该正确构建查询,而IIRC你可以交换范围的序列(例如featured
之后的cheapest
),如果你希望它们以不同的方式应用。