J'essaie de trouver tous les utilisateurs avec un identifiant supérieur à 200, mais j'ai des problèmes avec la syntaxe spécifique.
User.where(:id > 200)
et
User.where("? > 200", :id)
ont tous deux échoué.
Aucune suggestion?
ruby-on-rails
syntax
where
Adam Templeton
la source
la source
?
, plutôt que d'intégrer le200
?Je n'ai testé cela que dans Rails 4 mais il existe une manière intéressante d'utiliser une plage avec un
where
hachage pour obtenir ce comportement.générera le SQL
La même chose peut être faite pour moins qu'avec
-Float::INFINITY
.Je viens de publier une question similaire demandant de faire cela avec des dates ici sur SO .
>=
contre>
Pour éviter que les gens n'aient à fouiller et à suivre la conversation des commentaires, voici les faits saillants.
La méthode ci-dessus génère uniquement une
>=
requête et non un fichier>
. Il existe de nombreuses façons de gérer cette alternative.Pour les nombres discrets
Vous pouvez utiliser une
number_you_want + 1
stratégie comme ci-dessus où je suis intéressé par les utilisateurs avecid > 200
mais que vous recherchez en faitid >= 201
. C'est parfait pour les nombres entiers et les nombres où vous pouvez incrémenter d'une seule unité d'intérêt.Si vous avez extrait le nombre dans une constante bien nommée, cela peut être le plus facile à lire et à comprendre en un coup d'œil.
Logique inversée
Nous pouvons utiliser le fait que
x > y == !(x <= y)
et utiliser la chaîne where not.qui génère le SQL
Cela prend une seconde de plus à lire et à raisonner, mais fonctionnera pour les valeurs non discrètes ou les colonnes où vous ne pouvez pas utiliser le
+ 1
stratégie.Table d'Arel
Si vous voulez avoir de la fantaisie, vous pouvez utiliser le
Arel::Table
.générera le SQL
Les spécificités sont les suivantes:
Cette approche vous donnera le SQL exact qui vous intéresse, mais peu de gens utilisent directement la table Arel et peuvent la trouver désordonnée et / ou déroutante. Vous et votre équipe saurez ce qui est le mieux pour vous.
Prime
À partir de Rails 5, vous pouvez également le faire avec des dates!
générera le SQL
Bonus double
Une fois Ruby 2.6 sorti (25 décembre 2018), vous pourrez utiliser la nouvelle syntaxe de plage infinie! Au lieu de cela,
201..Float::INFINITY
vous pourrez simplement écrire201..
. Plus d'informations dans ce billet de blog .la source
where
matchers de base . Car>
je suggère d'utiliser un>= (number_you_want + 1)
pour plus de simplicité. Si vous voulez vraiment vous assurer qu'il ne s'agit que d'une>
requête, vous pouvez accéder à la table ARel. Chaque classe qui hérite deActiveRecord
a unearel_table
méthode getter qui renvoie leArel::Table
pour cette classe. Les colonnes de la table sont accessibles avec la[]
méthode commeUser.arel_table[:id]
. Cela renvoie un queArel::Attributes::Attribute
vous pouvez appelergt
et transmettre200
. Cela peut ensuite être transmis àwhere
. par exempleUser.where(User.arel_table[:id].gt(200))
.User.where(created_at: 3.days.ago..DateTime::Infinity.new)
.WHERE (users.created_at >= '2016-04-09 14:31:15' AND users.created_at < #<Date::Infinity:0x00>)
(les graduations arrière autour des noms de table et de colonne omises pour le formatage des commentaires SO).Une meilleure utilisation consiste à créer une étendue dans le modèle utilisateur
where(arel_table[:id].gt(id))
la source
Si vous voulez une écriture plus intuitive, il existe un joyau appelé squeel qui vous permettra d'écrire votre instruction comme ceci:
Notez les caractères "accolades" {} et
id
sont qu'un texte.Tout ce que vous avez à faire est d'ajouter squeel à votre Gemfile:
Cela peut vous faciliter la vie lors de l'écriture d'instructions SQL complexes dans Ruby.
la source
Arel est votre ami.
la source
Une autre possibilité sophistiquée est ...
Cette fonctionnalité vous permet de créer des requêtes plus compréhensibles si vous souhaitez remplacer à plusieurs endroits, par exemple ...
Cela a plus de sens que d'avoir beaucoup
?
sur la requête ...la source
J'ai souvent ce problème avec les champs de date (où les opérateurs de comparaison sont très courants).
Pour approfondir la réponse de Mihai, qui, à mon avis, est une approche solide.
Aux modèles, vous pouvez ajouter des portées comme ceci:
... puis dans votre manette, ou partout où vous utilisez votre modèle:
... un exemple plus complexe avec des jointures ressemble à ceci:
Un énorme avantage de cette approche est (a) qu'elle vous permet de composer vos requêtes à partir de différentes étendues et (b) évite les collisions d'alias lorsque vous rejoignez deux fois la même table car arel_table gérera cette partie de la génération de requête.
la source
Rails 6.1+
Rails 6.1 a ajouté une nouvelle `` syntaxe '' pour les opérateurs de comparaison dans les
where
conditions, par exemple:Ainsi, votre requête peut être réécrite comme suit:
Voici un lien vers PR où vous pouvez trouver plus d'exemples.
la source
Plus court:
la source
where("id > ?", 200)
syntaxe). Cela n'atteint pas cela.