Przestarzałe ostrzeżenie dla Rails 4 has_many z zamówieniem

105
class RelatedList < ActiveRecord::Base
  extend Enumerize

  enumerize :list_type, in: %w(groups projects)

  belongs_to :content
  has_many :contents, :order => :position

end

Mam ten model w mojej aplikacji rails, która wyświetla ostrzeżenie, gdy próbuję utworzyć rekordy w konsoli.

OSTRZEŻENIE O DEPRECATION: Następujące opcje w Twojej RelatedList.has_many: deklaracja zawartości są nieaktualne:: order. Zamiast tego użyj bloku zakresu. Na przykład: has_many: spam_comments, conditions: {spam: true}, class_name: 'Comment' należy przepisać w następujący sposób: has_many: spam_comments, -> {where spam: true}, class_name: 'Comment'. (wywoływane z /Users/shivam/Code/auroville/avorg/app/models/related_list.rb:7)

Wygląda na to, że Rails 4 ma nową: składnię kolejności do użycia w modelach, ale nie mogę znaleźć dokumentacji w przewodnikach Rails.

shankardevy
źródło

Odpowiedzi:

250

W Railsach 4 :orderjest przestarzały i musi zostać zastąpiony blokiem zasięgu lambda, jak pokazano w ostrzeżeniu, które opublikowałeś w pytaniu. Inną kwestią, na którą należy zwrócić uwagę, jest to, że ten blok zakresu musi zostać przekazany przed innymi opcjami asocjacji, takimi jak dependent: :destroy itp.

Spróbuj:

has_many :contents, -> { order(:position) }

Aby określić kierunek zamówienia, tj albo ascczy descjako @ Joshua-Coady i @wsprujit sugerują, przeznaczenie:

has_many :contents, -> { order 'position desc' }

lub używając stylu skrótu:

has_many :contents, -> { order(position: :desc) }

Dalsze informacje na temat zakresów Active Record dlahas_many .

vee
źródło
3
działa świetnie! gdzie mogę znaleźć takie informacje w przewodnikach lub dokumentach? Nie mogę znaleźć. dzięki.
shankardevy
4
A co, jeśli masz więcej niż jedną wycofaną opcję, powiedz oderi include? This: { order(:position), include(:track) }rzuca błąd w przecinek.
kakubei
2
Aby zamówić asc / desc, użyj-> { order(name: :asc) }
wspruijt
1
Jeśli z jakiegoś powodu chcesz po prostu czasami zamówić kolekcję, możesz również zrobić to, list.contents.order('position desc')co może być ogólnie bardziej wydajne, a nie jako model nachalny (w głosowanej odpowiedzi lista zna pole treści, tutaj kontroler to wie )
Dirty Henry
35

Zajęło mi trochę czasu, aby dowiedzieć się, jak to zrobić porządek i to, że w końcu stwierdziliśmy, że łańcuch zakres sprawozdań,

has_many :things, -> { includes(:stuff).order("somedate desc") }, class_name: "SomeThing"
sfoop
źródło
2
To był dokładnie mój problem. Próbuję ustalić, jak uporządkować relację has_many według atrybutu nadrzędnego. Nie zdawałem sobie sprawy, że możesz to zrobić, obejmuje to, a następnie zamówić. Dzięki!
Timothyashaw
27

Pomyślałem, że dodam, że jeśli masz jakieś argumenty haszujące opcji, muszą iść po lambdzie, w ten sposób:

has_many :things, -> { order :stuff }, dependent: :destroy

Zajęło mi minutę, zanim sam to zrozumiałem - mam nadzieję, że pomoże to każdemu, kto przychodzi do tego pytania, mając ten sam problem.

Wylliam Judd
źródło
3
Dotyczy to również skojarzeń „poprzez”, które mogą istnieć na obiekcie -has_many :items, -> { order 'name' }, through: :suppliers
Major Major
0

To działa dla mnie z Rails 4 i MongoDB

has_many :discounts, order: :min_amount.asc
Dave
źródło
-4

Alternatywnie możesz umieścić orderklauzulę na modelu, na przykład:

has_many :options, order: 'name' # In class Answer

Staje się

has_many :options # In class Answer

default_scope { order 'name' } # In class Option

PS: Mam, ArgumentError: wrong number of arguments (1 for 0)kiedy robię has_many :things, -> {}.

dorycki
źródło
4
Nie używaj zakresu domyślnego. Jeśli jesteś do tego przyzwyczajony, możesz dodać do tej magicznej metody więcej logiki. Trudno to zmienić w przyszłości.
Grzegorz Łuszczek