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

时间:2012-03-16 23:45:32

标签: ruby-on-rails activerecord rails-activerecord default-scope

基本上我有两个课程,预订作者。书籍可以有多个作者,作者可以有多本书。书籍具有以下默认范围。

default_scope :order => "publish_at DESC"

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

@author = Author.find(params[:id])
@books = @author.books

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

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

@books = @author.books.sort_by_popularity

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

@books = @author.books.unscoped.sort_by_popularity # returns all books in database

我想知道我是否可以使用ActiveRelation except() method 做这样的事情(似乎它应该工作,但事实并非如此。它忽略了顺序,而不是当它是default_scope命令时)

def sort_by_popularity
  self.except(:order).do_some_joining_magic.order('popularity ASC')
  #    |------------|                       |---------------------|
end

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

2 个答案:

答案 0 :(得分:28)

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

  

<强>重排序(*参数)
  用指定的顺序替换在关系上定义的任何现有订单。

这样的事情:

def self.sort_by_popularity
  scoped.do_some_joining_magic.reorder('popularity ASC')
end

而且我认为您想要使用类方法而scoped代替self,但我不知道整个背景,所以也许我错了。

我不知道为什么except无效。 default_scope似乎在最后(某种程度上)应用而不是从头开始,但我还没有对它进行过多次调查。

答案 1 :(得分:0)

您可以做到这一点而不会丢失default_scope或其他顺序

@books.order_values.prepend 'popularity ASC'