仅覆盖默认范围(特别是顺序),而不是Rails中的其他内容

Rya*_*yan 12 activerecord ruby-on-rails default-scope rails-activerecord

所以基本上我有两个班,作者.书籍可以有多个作者,作者可以有多本书.书籍具有以下默认范围.

default_scope :order => "publish_at DESC"
Run Code Online (Sandbox Code Playgroud)

在作者展示页面上,我想列出与该作者相关的所有书籍,所以我说以下内容......

@author = Author.find(params[:id])
@books = @author.books
Run Code Online (Sandbox Code Playgroud)

到目前为止一切都很好.作者#show页面列出了按出版日期排序的所有属于该作者的书籍.

我也在研究一种能够按照书籍的受欢迎程度排序的宝石.

@books = @author.books.sort_by_popularity
Run Code Online (Sandbox Code Playgroud)

问题是每当它尝试排序时,default_scope总是会妨碍.如果我试图取消它之前它将摆脱作者关系并返回数据库中的每本书.例如

@books = @author.books.unscoped.sort_by_popularity # returns all books in database
Run Code Online (Sandbox Code Playgroud)

我想知道我是否可以使用ActiveRelation except()方法 做这样的事情(看起来它应该工作,但事实并非如此.它忽略了顺序,只是当它是default_scope命令时)

def sort_by_popularity
  self.except(:order).do_some_joining_magic.order('popularity ASC')
  #    |------------|                       |---------------------|
end
Run Code Online (Sandbox Code Playgroud)

关于为什么这不起作用的任何想法?关于如何以不同的方式工作的任何想法?我知道我可以摆脱default_scope,但我想知道是否还有另一种方法可以做到这一点.

mu *_*ort 28

您应该可以reorder用来完全替换现有的ORDER BY:

reorder(*args)
用指定的顺序替换在关系上定义的任何现有顺序.

所以像这样:

def self.sort_by_popularity
  scoped.do_some_joining_magic.reorder('popularity ASC')
end
Run Code Online (Sandbox Code Playgroud)

而且我认为你想要使用类方法,而scoped不是self但我不知道整个上下文,所以也许我错了.

我不知道为什么except不起作用.在default_scope似乎变得末(那种),而不是一开始申请,但我还没有看进去那么多.