Si j'ai une portée avec un lambda et qu'il faut un argument, selon la valeur de l'argument, je sais peut-être qu'il n'y aura pas de correspondance, mais je veux toujours renvoyer une relation, pas un tableau vide:
scope :for_users, lambda { |users| users.any? ? where("user_id IN (?)", users.map(&:id).join(',')) : [] }
Ce que je veux vraiment, c'est une méthode "none", l'opposé de "all", qui renvoie une relation qui peut encore être chaînée, mais qui entraîne un court-circuit de la requête.
Réponses:
Il existe désormais un mécanisme "correct" dans Rails 4:
la source
Model.scoped
fait ce que vous cherchez dans les rails 3.Model.none
ne fonctionne pas. Vous devez utiliser l'un de vos vrais noms de modèle, par exempleUser.none
ou ce que vous avez.Une solution plus portable qui ne nécessite pas de colonne "id" et ne suppose pas qu'il n'y aura pas de ligne avec un id de 0:
Je cherche toujours une manière plus "correcte".
la source
scope :none, -> { where("false") }
Venir dans Rails 4
Dans Rails 4, une chaîne
ActiveRecord::NullRelation
sera renvoyée à partir d'appels commePost.none
.Ni elle, ni les méthodes chaînées, ne généreront de requêtes dans la base de données.
Selon les commentaires:
Voir le code source .
la source
Vous pouvez ajouter une étendue appelée "aucune":
Cela vous donnera un ActiveRecord :: Relation vide
Vous pouvez également l'ajouter à ActiveRecord :: Base dans un initialiseur (si vous le souhaitez):
Beaucoup de façons d'obtenir quelque chose comme ça, mais certainement pas la meilleure chose à garder dans une base de code. J'ai utilisé la portée: aucune pour refactoriser et trouver que je dois garantir un ActiveRecord :: Relation vide pendant une courte période.
la source
where('1=2')
pourrait être un peu plus concisModel.none
comment procéder?Est une solution dangereuse car votre portée peut être enchaînée.
User.none.first
renverra le premier utilisateur. Il est plus sûr d'utiliser
la source
Je pense que je préfère la façon dont cela ressemble aux autres options:
Menant à quelque chose comme ça:
la source
where(false)
ne ferait pas le travail - cela laisse la portée inchangée.limit(0)
sera remplacé si vous appelez.first
ou.last
plus tard dans la chaîne, car Rails s'ajouteraLIMIT 1
à cette requête.none
relation mentionnée ci-dessous.Utilisez la portée:
Mais, vous pouvez également simplifier votre code avec:
Si vous voulez un résultat vide, utilisez ceci (supprimez la condition if):
la source
C'est possible et c'est donc:
http://apidock.com/rails/v4.0.2/ActiveRecord/QueryMethods/none
Corrige moi si je me trompe.
la source
Il existe également des variantes, mais toutes demandent à db
la source
where(false)
ouwhere(nil)
est simplement ignoré.