Avviso deprecato per Rails 4 has_many with order


105
class RelatedList < ActiveRecord::Base
  extend Enumerize

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

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

end

Ho questo modello nella mia app rails che lancia un avviso quando provo a creare record nella console.

AVVISO DI DEPRECAZIONE: Le seguenti opzioni nella dichiarazione RelatedList.has_many: content sono deprecate:: order. Utilizza invece un blocco di ambito. Ad esempio, quanto segue: has_many: spam_comments, condizioni: {spam: true}, class_name: 'Comment' deve essere riscritto come segue: has_many: spam_comments, -> {where spam: true}, class_name: 'Comment'. (chiamato da /Users/shivam/Code/auroville/avorg/app/models/related_list.rb:7)

Sembra che Rails 4 abbia una nuova sintassi: order per l'uso nei modelli, ma non riesco a trovare la documentazione in Rails Guides.

Risposte:


250

In Rails 4, :orderè stato deprecato e deve essere sostituito con il blocco dell'ambito lambda come mostrato nell'avviso che hai pubblicato nella domanda. Un altro punto da notare è che questo blocco di ambito deve essere passato prima di qualsiasi altra opzione di associazione come dependent: :destroy ecc.

Provalo:

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

Per specificare la direzione dell'ordine, ad esempio asco desccome suggerito da @ joshua-coady e @wsprujit, usa:

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

oppure, usando lo stile hash:

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

Ulteriori riferimenti sugli ambiti di record attivi perhas_many .


3
funziona alla grande! dove posso trovare tali informazioni nelle guide o nei documenti? Non riesco a trovarne uno. Grazie.
Shankardevy


4
E se hai più di un'opzione deprecata, ad esempio odere include? Questo: { order(:position), include(:track) }genera un errore sulla virgola.
kakubei

2
Per ordinare asc / desc, usa-> { order(name: :asc) }
wspruijt

1
Se per qualche motivo vuoi solo che la collezione venga ordinata qualche volta, puoi anche fare ciò list.contents.order('position desc')che può essere più efficiente nel complesso, e non come modello invadente (nella risposta votata, l'elenco conosce un campo di contenuto, qui lo sa il controllore )
Dirty Henry

35

Mi ci è voluto un po 'per capire come ordinare e includere, alla fine ho scoperto che concatenate le dichiarazioni di ambito ,

has_many :things, -> { includes(:stuff).order("somedate desc") }, class_name: "SomeThing"

2
Questo era esattamente il mio problema. Sto cercando di capire come ordinare una relazione has_many in base a un attributo genitore. Non avevo capito che puoi fare include come questo e poi ordinare. Grazie!
timothyashaw

27

Ho solo pensato di aggiungere che se hai qualche opzione hash argomenti, devono andare dopo il lambda, in questo modo:

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

Mi ci è voluto un minuto per capirlo da solo - si spera che aiuti chiunque altro venga a questa domanda avendo lo stesso problema.


3
Questo vale anche per le associazioni "passanti" che potrebbero esistere sull'oggetto -has_many :items, -> { order 'name' }, through: :suppliers
Maggiore Maggiore

0

Questo funziona per me con Rails 4 e MongoDB

has_many :discounts, order: :min_amount.asc

-4

In alternativa, puoi inserire la orderclausola sul modello, ad esempio:

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

diventa

has_many :options # In class Answer

default_scope { order 'name' } # In class Option

PS: ho ottenuto ArgumentError: wrong number of arguments (1 for 0)quando lo faccio has_many :things, -> {}.


4
Non utilizzare l'ambito predefinito. Se sei abituato a farlo, puoi aggiungere a quel metodo magico più logica. È difficile ignorarlo in futuro.
Grzegorz Łuszczek
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.