Rails ORDER BY根据型号的不同而不同

时间:2017-10-10 19:12:52

标签: ruby-on-rails

我正在尝试在我在rails应用程序中构建的一些表中实现可排序列。

我有两个不同的模型。一个是“投注”:

class Bet < ApplicationRecord
  validates :title, presence: true, length: { maximum: 50 }
  validates :benchmark, presence: true
  has_many :picks, dependent: :destroy
end

另一个是“Picks”,属于两个资源,用户和投注(上图)。

class Pick < ApplicationRecord
  belongs_to :user
  belongs_to :bet
  default_scope -> { order(created_at: :desc) }
  validates :user_id, presence: true
  validates :bet_id, presence: true
end

Bets and Picks都有一个“Benchmark”值,这是一个浮点数。

当我进入rails console并调用此命令时:

@bets = Bet.all.order("benchmark")

我明白了:

 Bet Load (0.6ms)  SELECT  "bets".* FROM "bets" ORDER BY benchmark LIMIT ?  [["LIMIT", 11]]

这就是我想要的。如果我打印出所有@bets的基准,它们就会按顺序打印。

然而,当我为选秀权做同样的事情时,我明白了:

@picks = Pick.all.order("benchmark")

Pick Load (1.2ms)  SELECT  "picks".* FROM "picks" **ORDER BY "picks"."created_at" DESC**, benchmark LIMIT ?  [["LIMIT", 11]]

无论我做什么,它只会通过“选择”命令选择。“created_at”DESC。

我在这里缺少什么?

1 个答案:

答案 0 :(得分:0)

您看到的问题是由default_scope模型的Pick造成的。这将使所有默认查询都使用该范围。正如您在生成的SQL中看到的那样,它首先按created_at desc排序,然后是您使用的任何其他订单属性。

默认范围一直被认为是rails中的反模式,因为它会导致您所看到的问题。有两种方法可以解决这个问题。

1)如果您不确定在代码库中使用此默认作用域的位置,您可能希望保留它。要绕过默认范围,请使用unscoped将其从您正在进行的当前查询中删除。

@picks = Pick.all.unscoped.order("benchmark")

2)如果您当前没有在任何地方使用该默认范围。将其从课程中删除,并将其替换为普通scope

class Pick < ApplicationRecord
  belongs_to :user
  belongs_to :bet
  scope :order_newest -> { order(created_at: :desc) }
  validates :user_id, presence: true
  validates :bet_id, presence: true
end

# Use like this
@picks = Pick.all.order_newest