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?
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?
Réponses:
Essaye ça
User.where("id > ?", 200)
?
, plutôt que d'intégrer le 200
?
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.
User.where(id: 201..Float::INFINITY)
générera le SQL
SELECT `users`.* FROM `users` WHERE (`users`.`id` >= 201)
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 avec id > 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.
User.where.not(id: -Float::INFINITY..200)
qui génère le SQL
SELECT `users`.* FROM `users` WHERE (NOT (`users`.`id` <= 200))
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
.
User.where(User.arel_table[:id].gt(200))
générera le SQL
"SELECT `users`.* FROM `users` WHERE (`users`.`id` > 200)"
Les spécificités sont les suivantes:
User.arel_table #=> an Arel::Table instance for the User model / users table
User.arel_table[:id] #=> an Arel::Attributes::Attribute for the id column
User.arel_table[:id].gt(200) #=> an Arel::Nodes::GreaterThan which can be passed to `where`
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.
À partir de Rails 5, vous pouvez également le faire avec des dates!
User.where(created_at: 3.days.ago..DateTime::Infinity.new)
générera le SQL
SELECT `users`.* FROM `users` WHERE (`users`.`created_at` >= '2018-07-07 17:00:51')
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 écrire 201..
. Plus d'informations dans ce billet de blog .
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 de ActiveRecord
a une arel_table
méthode getter qui renvoie le Arel::Table
pour cette classe. Les colonnes de la table sont accessibles avec la []
méthode comme User.arel_table[:id]
. Cela renvoie un que Arel::Attributes::Attribute
vous pouvez appeler gt
et transmettre 200
. Cela peut ensuite être transmis à where
. par exemple User.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).
Si vous voulez une écriture plus intuitive, il existe un joyau appelé squeel qui vous permettra d'écrire votre instruction comme ceci:
User.where{id > 200}
Notez les caractères "accolades" {} et id
sont qu'un texte.
Tout ce que vous avez à faire est d'ajouter squeel à votre Gemfile:
gem "squeel"
Cela peut vous faciliter la vie lors de l'écriture d'instructions SQL complexes dans Ruby.
Une autre possibilité sophistiquée est ...
User.where("id > :id", id: 100)
Cette fonctionnalité vous permet de créer des requêtes plus compréhensibles si vous souhaitez remplacer à plusieurs endroits, par exemple ...
User.where("id > :id OR number > :number AND employee_id = :employee", id: 100, number: 102, employee: 1205)
Cela a plus de sens que d'avoir beaucoup ?
sur la requête ...
User.where("id > ? OR number > ? AND employee_id = ?", 100, 102, 1205)
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:
scope :updated_at_less_than, -> (date_param) {
where(arel_table[:updated_at].lt(date_param)) }
... puis dans votre manette, ou partout où vous utilisez votre modèle:
result = MyModel.updated_at_less_than('01/01/2017')
... un exemple plus complexe avec des jointures ressemble à ceci:
result = MyParentModel.joins(:my_model).
merge(MyModel.updated_at_less_than('01/01/2017'))
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.
Rails 6.1 a ajouté une nouvelle `` syntaxe '' pour les opérateurs de comparaison dans les where
conditions, par exemple:
Post.where('id >': 9)
Post.where('id >=': 9)
Post.where('id <': 3)
Post.where('id <=': 3)
Ainsi, votre requête peut être réécrite comme suit:
User.where('id >': 200)
Voici un lien vers PR où vous pouvez trouver plus d'exemples.
Plus court:
User.where("id > 200")
where("id > ?", 200)
syntaxe). Cela n'atteint pas cela.