270 votes

Ordre de tri par défaut pour un modèle de rails ?

Je tiens à spécifier un ordre de tri par défaut dans mon modèle.

Alors que quand je fais un .where() sans spécifier .order() il utilise le tri par défaut. Mais si je spécifier une .order(), il remplace la valeur par défaut.

570voto

Michael Durrant Points 30342

default_scope (Rails 2.3, 3+, 4.0) fonctionne, voici la syntaxe exacte:

class Book < ActiveRecord::Base
  default_scope order('created_at DESC')
end

où created_at est le champ que vous souhaitez le tri par défaut pour être fait.
(default_scope :order => 'created_at DESC' pour les rails 2.x)

Remarque: l'ASC est le code à utiliser pour l'ascension et DESC est pour la descente (desc, PAS dsc !).
Une fois que vous êtes habitué à cela, vous pouvez également utiliser 'named_scope' (juste appelé "champ d'application" dans rails 3), par exemple

class Book < ActiveRecord::Base
  named_scope :published, :conditions => { :published => true }
  scope :confirmed, :conditions => { :confirmed => true } # Rails 3 - just 'scope'
end

:published champ d'application vous donne Book.published au lieu de Book.find(:published => true).

Avec rails 3+ vous pouvez "chaîne" de ces méthodes par la concaténation d'entre eux avec des périodes entre eux, donc, avec les étendues vous pouvez maintenant utiliser Book.published.confirmed.
Avec cette méthode, la requête n'est pas exécutée jusqu'à ce que les résultats réels sont nécessaires (évaluation différée), donc 7 étendues pourrait être enchaînés les uns aux autres, mais seulement traduit par 1 la requête de base de données, afin d'éviter les problèmes de performance d'exécution de 7 requêtes distinctes.

Vous pouvez utiliser un passé en paramètre comme une date ou un user_id (quelque chose qui va changer au moment de l'exécution et donc aura besoin que "d'évaluation différée", 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 l'étendue par défaut avec:

Book.with_exclusive_scope { find(:all) } 

ou encore mieux:

Book.unscoped.all

qui va désactiver tous les filtres (conditions) ou tri (order by).

Notez que la première version fonctionne dans Rails2+ alors que la deuxième (non délimité) est seulement pour Rails3+


Donc ... si vous êtes en train de penser, hmm, si ceux-ci sont comme les méthodes alors..., ouais, c'est exactement ce que ces étendues sont!
Ils sont comme avoir def self.method_name ...code... end , mais comme toujours avec rubis ce sont de belles peu de raccourcis syntaxiques (ou du sucre) pour rendre les choses plus facile pour vous!

En fait, ils appartiennent à la Classe des méthodes de niveau comme ils fonctionnent sur le 1 ensemble de tous les dossiers.

Leur format est en train de changer, cependant, avec des rails 4 il y a dépréciation d'avertissement lors de l'utilisation de #champ d'application sans passer par un objet appelable. Par exemple portée :rouge, où(couleur: rouge) devrait être changé en scope :red, -> { where(color: 'red') }.

Comme une note de côté, lorsqu'il est utilisé de manière incorrecte, par défaut_scope peut être utilisée à mauvais escient/abus.
C'est surtout quand il est utilisé pour les actions wheres'limiter (filtrage) la valeur par défaut de sélection (une mauvaise idée pour un défaut) plutôt que d'être simplement utilisé pour la commande de résultats.
Pour where sélections, il suffit d'utiliser la régulière nommé étendues. et d'ajouter ce champ dans la requête, par exemple, Book.all.publishedpublished est un nom de champ.

En conclusion, les étendues sont vraiment très bien et vous aider à pousser les choses dans le modèle pour un "modèle de graisse mince controller' Sécheuse approche.

116voto

Paul Oliver Points 1914

Une mise à jour rapide pour Michael excellente réponse ci-dessus.

Pour les Rails 4.0+, vous devez mettre votre tri dans un bloc comme ceci:

class Book < ActiveRecord::Base
  default_scope { order('created_at DESC') }
end

Notez que la déclaration de commande est placé dans un bloc notée par les accolades.

Ils ont changé parce que c'était trop facile de passer à quelque chose de dynamique (comme à l'heure actuelle). Cela supprime le problème parce que le bloc est évalué au moment de l'exécution. Si vous n'utilisez pas un bloc, vous obtiendrez ce message d'erreur:

Soutien à l'appel de #default_scope sans un bloc est supprimé. Par exemple, au lieu de default_scope where(color: 'red'), veuillez utiliser default_scope { where(color: 'red') }. (Alternativement, vous pouvez simplement redéfinir soi-même.default_scope.)

6voto

Slobodan Kovacevic Points 4622

Vous pouvez utiliser default_scope à mettre en œuvre un ordre de tri par défaut http://api.rubyonrails.org/classes/ActiveRecord/Scoping/Default/ClassMethods.html

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X