新手问题 关于 defaul order 的使用?

cqcn1991 · 2014年10月04日 · 最后由 torvaldsdb 回复于 2016年12月27日 · 2662 次阅读

比如,对于 tweets,在绝大多数情况下,我们可能希望的是按照新建日期排序 于是用

default_scope{order('created_at DESC')}

就很方便

但是,还有的时候,比如希望做个热度排行榜 那么,就希望按点击率排行

scope :order_by_hits, -> { order('hits DESC') }

但问题是没法直接使用第二个 scope,还需要加unscope tweets = Tweet.unscoped.order_by_hits,像这样。而且似乎还有很多潜在的问题 (http://stackoverflow.com/questions/1834159/overriding-a-rails-default-scope)

所以,请问一般情况下怎么用 scope? 是不用default_scope,而采用两个命名的 scope 分别使用吗?还是怎样?

按我的经验,建议这个默认排序用 scope 写!!!

为了身心健康,请避免用 default_scope

#2 楼 @billy +1

态度坚决地抵制 default scope,百害而无一利..

#3 楼 @hooopo ……完蛋了。 那具体怎么使用? 比如我希望一个 scope 是按 create_at 排列,一个是按 hits 排列。 就是每次都写清楚调用的是哪个 scope 么?

#4 楼 @cqcn1991

order('hits DESC')或 scope。

但千万别 default scope。除非你清楚在多个 order 或 where 的情况下 default scope 产生的 SQL 是什么样的,还有你的业务是否真的和 default scope 的应用场景一致。

@hooopo 顶。 单单从 Database 的角度来说,就要避免用 default_scope。因为 order/where 和 default scope 混到一起后,产生的 query 有可能非常低效,一个 naive 的例子,你在 hits 上有 index,created_at 上面没有,那你的取 sort by hits 的 query 本可以只做 B-tree scan,再去取相应的 table rows,由于 default_scope,现在就必须做一个 full table scan(因为 created_at 需要到 table 里面取)。

就算你在 created_at 上面加了一个 index,由于有两个 column 需要 sort,也要消耗额外的内存,做额外的 I/O 操作。总之,default_scope 几乎就是用 DB 的消耗来换 syntax sugar。don't be lazy,把你需要的操作明确地写出来,否则就可能发生你意想不到的事情。

#6 楼 @yijunlin 噢!就是说合并产生的 SQL 其实非常的低效,对吧?

话说有办法去给 Rails 提交代码改这个问题么,哈哈哈哈

#7 楼 @cqcn1991 不是 Rails 产生的 SQL 低效,而是用户要 Rails 做的操作一定会产生低效的 SQL。当你不需要用 updated_at 来 sort 的时候,你还是要去 Rails 去读 updated_at 的信息,Rails 是不可能 smart 到不用 updated_at 来 sort 吧:) 如果你写了 default_scope,Rails 就一定会去碰 updated_at,碰了就是低效。

scope :order_by_hits, -> { order('hits DESC') }尽管这个可以作为一个排序的 scope, 它还只是一个 scope.

需要 登录 后方可回复, 如果你还没有账号请 注册新账号