Переопределить только область по умолчанию (в частности, порядок) и ничего больше в Rails - PullRequest
12 голосов
/ 17 марта 2012

Итак, в основном у меня есть два класса: Книга и Автор .Книги могут иметь несколько авторов, а авторы могут иметь несколько книг.Книги имеют следующую область по умолчанию.

default_scope :order => "publish_at DESC"

На странице "Показать автора" я хочу перечислить все книги, связанные с этим автором, поэтому я говорю следующее ...

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

Всепока хорошо.Автор # show page перечисляет все книги, принадлежащие этому автору, упорядоченные по дате публикации.

Я также работаю над драгоценным камнем, который может сортировать по популярности книги.

@books = @author.books.sort_by_popularity

Проблема состоит в том, что всякий раз, когда он пытается сортировать, default_scope всегда мешает.И если я попытаюсь снять его, прежде чем он избавится от отношения автора и вернет каждую книгу в базе данных.Например,

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

Мне интересно, могу ли я использовать ActiveRelation кроме () метода , чтобы сделать что-то подобное (кажется, что оно должно работать, но это не так.игнорирует порядок, только не тогда, когда это порядок default_scope)

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

Есть идеи, почему это не работает?Любые идеи о том, как заставить это работать по-другому?Я знаю, что могу просто избавиться от default_scope, но мне интересно, есть ли другой способ сделать это.

Ответы [ 2 ]

28 голосов
/ 17 марта 2012

Вы должны иметь возможность использовать reorder для полной замены существующего ЗАКАЗА ПО:

изменить порядок (* аргументы)
Заменяетлюбой существующий порядок, определенный в отношении с указанным порядком.

Так что-то вроде этого:

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

И я думаю, что вы хотите использовать метод класса для этого и scoped вместо self но я не знаю всего контекста, так что, возможно, я ошибаюсь.

Я не знаю, почему except не работает.default_scope, кажется, применяется в конце (вроде), а не в начале, но я не слишком много в этом разбираюсь.

0 голосов
/ 22 июля 2018

Вы можете сделать это без потери default_scope или другого заказа

@books.order_values.prepend 'popularity ASC'
...