Je voudrais spécifier un ordre de tri par défaut dans mon modèle.
De sorte que lorsque je fais un .where()
sans spécifier un, .order()
il utilise le tri par défaut. Mais si je spécifie un .order()
, il remplace la valeur par défaut.
Je voudrais spécifier un ordre de tri par défaut dans mon modèle.
De sorte que lorsque je fais un .where()
sans spécifier un, .order()
il utilise le tri par défaut. Mais si je spécifie un .order()
, il remplace la valeur par défaut.
Réponses:
default_scope
Cela fonctionne pour Rails 4+:
class Book < ActiveRecord::Base
default_scope { order(created_at: :desc) }
end
Pour Rails 2.3, 3, vous en avez besoin à la place:
default_scope order('created_at DESC')
Pour Rails 2.x:
default_scope :order => 'created_at DESC'
Où se created_at
trouve le champ sur lequel vous souhaitez effectuer le tri par défaut.
Remarque: ASC est le code à utiliser pour Croissant et DESC est pour décroissant ( desc
, PAS dsc
!).
scope
Une fois que vous y êtes habitué, vous pouvez également utiliser scope
:
class Book < ActiveRecord::Base
scope :confirmed, :conditions => { :confirmed => true }
scope :published, :conditions => { :published => true }
end
Pour Rails 2 dont vous avez besoin named_scope
.
:published
portée vous donne Book.published
au lieu de
Book.find(:published => true)
.
Depuis Rails 3, vous pouvez `` enchaîner '' ces méthodes en les concaténant avec des points entre elles, donc avec les étendues ci-dessus, vous pouvez maintenant utiliser Book.published.confirmed
.
Avec cette méthode, la requête n'est pas réellement exécutée jusqu'à ce que les résultats réels soient nécessaires (évaluation paresseuse), donc 7 étendues peuvent être chaînées ensemble mais ne résultant qu'en 1 requête de base de données réelle, pour éviter des problèmes de performances lors de l'exécution de 7 requêtes distinctes.
Vous pouvez utiliser un paramètre passé tel qu'une date ou un user_id (quelque chose qui changera au moment de l'exécution et aura donc besoin de cette 'évaluation paresseuse', avec un lambda, comme ceci:
scope :recent_books, lambda
{ |since_when| where("created_at >= ?", since_when) }
# Note the `where` is making use of AREL syntax added in Rails 3.
Enfin, vous pouvez désactiver la portée par défaut avec:
Book.with_exclusive_scope { find(:all) }
ou encore mieux:
Book.unscoped.all
ce qui désactivera tout filtre (conditions) ou tri (ordre par).
Notez que la première version fonctionne dans Rails2 + tandis que la seconde (non étendue) est uniquement pour Rails3 +
Donc
... si vous pensez, hmm, donc ce sont juste des méthodes alors ..., ouais, c'est exactement ce que sont ces étendues!
Ils sont comme avoir def self.method_name ...code... end
mais comme toujours avec rubis ce sont de jolis petits raccourcis syntaxiques (ou «sucre») pour vous faciliter les choses!
En fait, ce sont des méthodes au niveau de la classe car elles opèrent sur le 1 jeu d'enregistrements «tous».
Leur format change cependant, avec les rails 4, il y a un avertissement de dépréciation lors de l'utilisation de #scope sans passer un objet appelable. Par exemple, portée: rouge, où (couleur: «rouge») doit être remplacé parscope :red, -> { where(color: 'red') }
.
En remarque, lorsqu'il est utilisé de manière incorrecte, _scope par défaut peut être mal utilisé / abusé.
Cela concerne principalement le moment où il est utilisé pour des actions telles que where
la limitation (filtrage) de la sélection par défaut (une mauvaise idée pour une valeur par défaut) plutôt que d'être simplement utilisé pour ordonner les résultats.
Pour les where
sélections, utilisez simplement les étendues nommées standard. et ajoutez cette étendue dans la requête, par exemple Book.all.published
où published
est une étendue nommée.
En conclusion, les portées sont vraiment géniales et vous aident à pousser les choses dans le modèle pour une approche DRYer de `` contrôleur de modèle mince ''.
default_scope { order("#{table_name}.created_at DESC") }
?
default_scope { order(created_at: :desc) }
4.2.6
Semble au moins trier par updated_at
non created_at
.
updated_at
par défaut? : - |
Une mise à jour rapide de l'excellente réponse de Michael ci-dessus.
Pour Rails 4.0+, vous devez placer votre tri dans un bloc comme celui-ci:
class Book < ActiveRecord::Base
default_scope { order('created_at DESC') }
end
Notez que l'instruction order est placée dans un bloc désigné par les accolades.
Ils l'ont changé parce qu'il était trop facile de passer quelque chose de dynamique (comme l'heure actuelle). Cela supprime le problème car le bloc est évalué au moment de l'exécution. Si vous n'utilisez pas de bloc, vous obtiendrez cette erreur:
La prise en charge de l'appel de #default_scope sans bloc est supprimée. Par exemple, au lieu de
default_scope where(color: 'red')
, veuillez utiliserdefault_scope { where(color: 'red') }
. (Alternativement, vous pouvez simplement redéfinir self.default_scope.)
Comme @Dan mentionne dans son commentaire ci-dessous, vous pouvez faire une syntaxe plus rubis comme celle-ci:
class Book < ActiveRecord::Base
default_scope { order(created_at: :desc) }
end
ou avec plusieurs colonnes:
class Book < ActiveRecord::Base
default_scope { order({begin_date: :desc}, :name) }
end
Merci @Dan !
default_scope { order(created_at: :desc) }
si, comme moi, vous essayez de minimiser la syntaxe SQL dans les rails. <br/> Si vous avez plusieurs colonnes à classer et que vous souhaitez utiliser la nouvelle syntaxe, vous devrez peut-être envelopper la desc colonnes dans des moustaches comme celle-cidefault_scope { order({begin_date: :desc}, :name) }
Vous pouvez utiliser default_scope pour implémenter un ordre de tri par défaut http://api.rubyonrails.org/classes/ActiveRecord/Scoping/Default/ClassMethods.html
default_scope
sur cette page, car il a été refactorisé depuis ActiveRecord::Base
en ActiveRecord::Scoping::Default::ClassMethods
( api.rubyonrails.org/classes/ActiveRecord/Scoping/Default/… )