更改' ORDER BY' ActiveRecord子集上的链

时间:2017-03-08 06:48:24

标签: ruby-on-rails ruby activerecord sql-order-by rails-activerecord

背景:

我有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)

但我确信有更好的解决方案需要您的支持才能实现。

1 个答案:

答案 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),如果你希望它们以不同的方式应用。