J'ai uniquement testé sur des Rails 4, mais il y a un moyen intéressant d'utiliser un éventail avec une where de hachage pour obtenir ce comportement.
User.where(id:201..Float::INFINITY)
va générer le SQL
SELECT `users`.* FROM `users` WHERE (`users`.`id`>=201)
La même chose peut être fait pour moins de avec -Float::INFINITY.
Je viens de poster une question similaire demander au sujet de faire cela avec des dates ici DONC.
>= vs >
Pour éviter que les gens d'avoir à creuser à travers et suivez les commentaires de la conversation ici les faits saillants.
La méthode ci-dessus ne génère un >= requête et pas un >. Il existe de nombreuses façons de gérer cette alternative.
Pour les nombres discrets
Vous pouvez utiliser un number_you_want + 1 stratégie comme ci-dessus, où je suis intéressé par les Utilisateurs avec id > 200 mais effectivement regarder pour id >= 201. C'est très bien pour les entiers et les nombres, où vous pouvez incrémenter d'une unité d'intérêt.
Si vous avez le numéro de l'extrait dans un bien nommée constante de ce qui peut être le plus facile à lire et à comprendre en un clin d'œil.
Logique inversée
Nous pouvons utiliser le fait que x > y == !(x <= y) et utiliser les où les pas de la chaîne.
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 à lire et à raison, mais de travail pour les non valeurs discrètes ou les colonnes où vous ne pouvez pas utiliser la + 1 stratégie.
Arel table
Si vous voulez obtenir la fantaisie, vous pouvez faire usage de la Arel::Table.
User.where(User.arel_table[:id].gt(200))
va générer le SQL
"SELECT `users`.* FROM `users` WHERE (`users`.`id` > 200)"
Les détails sont comme suit:
User.arel_table #=> an Arel::Table instance for the User model /users tableUser.arel_table[:id]#=> an Arel::Attributes::Attribute for the id columnUser.arel_table[:id].gt(200)#=> an Arel::Nodes::GreaterThan which can be passed to `where`
Cette approche, vous aurez l' exacte SQL qui vous intéresse cependant pas beaucoup de gens utilisent le Arel table directement et pouvez le trouver en désordre et/ou de confusion. Vous et votre équipe va savoir ce qui est le mieux pour vous.
Bonus
De départ dans les Rails 5, vous pouvez également le faire avec des dates!
SELECT `users`.* FROM `users` WHERE (`users`.`created_at`>='2018-07-07 17:00:51')
Double Bonus
Une fois Ruby 2.6 est sorti (le 25 décembre 2018), vous serez en mesure d'utiliser la nouvelle gamme infinie de la syntaxe! Au lieu de 201..Float::INFINITY vous serez en mesure de simplement écrire 201... Plus d'infos dans ce blog.
Cette réponse est le meilleur pour les Rails 4 de l'OMI. Utilisé pendant un certain temps et fonctionne parfaitement.
Pourquoi est-ce supérieur à la accepté de répondre, par curiosité?
Supérieure est trompeuse. En général, vous atteindre plus de souplesse avec votre ARel requêtes si vous êtes en mesure d'utiliser le hachage de la syntaxe sur les chaînes qui est pourquoi beaucoup préfèrent cette solution. En fonction de votre projet/équipe/organisation, vous souhaitez peut-être quelque chose qui est plus facile pour quelqu'un en regardant le code de la figure, qui l'a accepté réponse est.
Les chaînes de manger aussi de la mémoire vs immuable littéraux (symboles, fixnums, etc.). Bien sûr, il prend un très gros projet pour vraiment faire une différence
Cela ne génère >= requête. Je teste même 201...Float::INFINITY mais aussi de générer des >= requête. Est-il possible de faire cela et d'obtenir un > requête?
Je ne crois pas que vous pouvez le faire en utilisant la base where de rapprochement. Pour > je vous suggérons d'utiliser un >= (number_you_want + 1) pour des raisons de simplicité. Si vous voulez vraiment vous assurer qu'il est juste un > une requête, vous pouvez accéder à l'ARel table. Chaque classe qui hérite de ActiveRecord a un arel_table méthode de lecture qui renvoie le Arel::Table pour la classe. Des colonnes de la table sont accessibles avec le [] méthode comme User.arel_table[:id]. Il renvoie un Arel::Attributes::Attribute vous pouvez appeler gt et passer dans 200. Il peut ensuite être transmis à where. par exemple User.where(User.arel_table[:id].gt(200)).
Cette solution peut fonctionner, mais c'est moche de lecture. D'autres développeurs peuvent être confus par ce. L'OMI, l'utilisation de chaînes de caractères dans les cas où les conditions est quelque chose que les Rails de projet pourrait améliorer.
Je sais que les Rails 5 est d'obtenir un or méthode pour simplifier le conditionnel qui est génial. Tout va ARel est toujours une option pour les comparaisons mon commentaire précédent explique pourquoi certains préfèrent un peu plus laide de la syntaxe pour le chaînage de la flexibilité. Bien que la plupart des projets ne peut jamais obtenir assez complexe où l'un et l'autre la matière de sorte qu'il est tout au sujet de ce qui fonctionne le mieux pour vous, votre projet et de l'équipe.
Si vous voulez faire cela avec le temps: le Temps.courant...DateTime::Infinity.nouveau
pouvez-vous me donner un exemple? La suite n'est pas de travail pour moi User.where(created_at: 3.days.ago..DateTime::Infinity.new).
La honte je ne peux pas modifier le commentaire plus. J'ai raté la parenthèse autour de la fois entre les gammes, de manière correcte serait: où(temps: (Date.aujourd'hui.beginning_of_day)...(Date de.aujourd'hui.end_of_day))
les parens n'ont pas d'importance dans votre déclaration que la fin de la plage Date.today.end_of_day est traitée différemment de la DateTime::Infinity.new. Date.today.end_of_day va générer une gamme pour le timestamp entre, par opposition à un >= condition que prévu. Je peux aussi confirmer que l'ajout de parenthèses autour de la proposition initiale en tant que tel User.where(created_at: (3.days.ago)...(DateTime::Infinity.new)) aussi ne fonctionne pas.
Je suis en cours d'exécution le code que j'ai cité ci-dessus dans les rails 5 rubis 2.2.4 sans problèmes. Quelle erreur avez-vous?
Ah! Il est probable qu'un nouveau changement dans les Rails 5 qui vous offre une véritable comportement. Dans les Rails 4.2.5 (Ruby 2.2.2), vous obtiendrez une requête avec WHERE (users.created_at >= '2016-04-09 14:31:15' AND users.created_at < #<Date::Infinity:0x00>) (retour tiques autour de la table et de la colonne des noms omis pour une SORTE de commentaire de formatage).
WRT pour > précisément ce qui peut être accompli dans ce que je ressens est moins lisible, mais toujours exprimable par hachage. where.not(id: -Float::INFINITY..200) génère WHERE (NOT (`users`.`id` <= 200)) et x > 200 == !(x <= 200). Cela est nécessaire si l'on devait utiliser le hachage de la syntaxe pour un champ qui n'était pas un entier.
Si vous voulez un plus intuitive de l'écriture, il existe un joyau appelé squeel qui vous permettra d'écrire vos instructions, comme ceci:
User.where{id >200}
Notez le 'accolade' caractères { } et id être juste un texte.
Tout ce que vous avez à faire est d'ajouter squeel à votre Gemfile:
gem "squeel"
Cela peut faciliter votre vie beaucoup lors de l'écriture complexe de l'instruction SQL en Ruby.
Je recommande d'éviter d'utiliser squeel. À Long terme est difficile à maintenir et a parfois un comportement étrange. Il est également buggy avec certaines versions d'enregistrements
J'ai été en utilisant squeel depuis quelques années et toujours heureux avec elle. Mais Peut-être que ça vaut la peine d'essayer un autre ORM, comme la suite (<> squeel) par exemple, qui semble prometteuse fonctionnalités intéressantes pour remplacer ActiveRecord.
... et puis dans votre contrôleur, ou n'importe où en utilisant 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 (un), il vous permet de composer vos requêtes à partir de différentes portées et (b) évite alias collisions lorsque vous vous joignez à deux fois la même table depuis arel_table va gérer cette partie de la génération de requêtes.
Je suppose que ce doit être dynamique, et que l'affiche veut éviter une injection SQL en utilisant des requêtes paramétrées (where("id > ?", 200) syntaxe). Ce n'est pas d'atteindre cet objectif.
Essayer cette
?
, plutôt que d'inlining la200
?J'ai uniquement testé sur des Rails 4, mais il y a un moyen intéressant d'utiliser un éventail avec une
where
de hachage pour obtenir ce comportement.va générer le SQL
La même chose peut être fait pour moins de avec
-Float::INFINITY
.Je viens de poster une question similaire demander au sujet de faire cela avec des dates ici DONC.
>=
vs>
Pour éviter que les gens d'avoir à creuser à travers et suivez les commentaires de la conversation ici les faits saillants.
La méthode ci-dessus ne génère un
>=
requête et pas un>
. Il existe de nombreuses façons de gérer cette alternative.Pour les nombres discrets
Vous pouvez utiliser un
number_you_want + 1
stratégie comme ci-dessus, où je suis intéressé par les Utilisateurs avecid > 200
mais effectivement regarder pourid >= 201
. C'est très bien pour les entiers et les nombres, où vous pouvez incrémenter d'une unité d'intérêt.Si vous avez le numéro de l'extrait dans un bien nommée constante de ce qui peut être le plus facile à lire et à comprendre en un clin d'œil.
Logique inversée
Nous pouvons utiliser le fait que
x > y == !(x <= y)
et utiliser les où les pas de la chaîne.qui génère le SQL
Cela prend une seconde à lire et à raison, mais de travail pour les non valeurs discrètes ou les colonnes où vous ne pouvez pas utiliser la
+ 1
stratégie.Arel table
Si vous voulez obtenir la fantaisie, vous pouvez faire usage de la
Arel::Table
.va générer le SQL
Les détails sont comme suit:
Cette approche, vous aurez l' exacte SQL qui vous intéresse cependant pas beaucoup de gens utilisent le Arel table directement et pouvez le trouver en désordre et/ou de confusion. Vous et votre équipe va savoir ce qui est le mieux pour vous.
Bonus
De départ dans les Rails 5, vous pouvez également le faire avec des dates!
va générer le SQL
Double Bonus
Une fois Ruby 2.6 est sorti (le 25 décembre 2018), vous serez en mesure d'utiliser la nouvelle gamme infinie de la syntaxe! Au lieu de
201..Float::INFINITY
vous serez en mesure de simplement écrire201..
. Plus d'infos dans ce blog.>=
requête. Je teste même201...Float::INFINITY
mais aussi de générer des>=
requête. Est-il possible de faire cela et d'obtenir un>
requête?where
de rapprochement. Pour>
je vous suggérons d'utiliser un>= (number_you_want + 1)
pour des raisons de simplicité. Si vous voulez vraiment vous assurer qu'il est juste un>
une requête, vous pouvez accéder à l'ARel table. Chaque classe qui hérite deActiveRecord
a unarel_table
méthode de lecture qui renvoie leArel::Table
pour la classe. Des colonnes de la table sont accessibles avec le[]
méthode commeUser.arel_table[:id]
. Il renvoie unArel::Attributes::Attribute
vous pouvez appelergt
et passer dans200
. Il peut ensuite être transmis àwhere
. par exempleUser.where(User.arel_table[:id].gt(200))
.or
méthode pour simplifier le conditionnel qui est génial. Tout va ARel est toujours une option pour les comparaisons mon commentaire précédent explique pourquoi certains préfèrent un peu plus laide de la syntaxe pour le chaînage de la flexibilité. Bien que la plupart des projets ne peut jamais obtenir assez complexe où l'un et l'autre la matière de sorte qu'il est tout au sujet de ce qui fonctionne le mieux pour vous, votre projet et de l'équipe.User.where(created_at: 3.days.ago..DateTime::Infinity.new)
.Date.today.end_of_day
est traitée différemment de laDateTime::Infinity.new
.Date.today.end_of_day
va générer une gamme pour le timestamp entre, par opposition à un>=
condition que prévu. Je peux aussi confirmer que l'ajout de parenthèses autour de la proposition initiale en tant que telUser.where(created_at: (3.days.ago)...(DateTime::Infinity.new))
aussi ne fonctionne pas.WHERE (users.created_at >= '2016-04-09 14:31:15' AND users.created_at < #<Date::Infinity:0x00>)
(retour tiques autour de la table et de la colonne des noms omis pour une SORTE de commentaire de formatage).>
précisément ce qui peut être accompli dans ce que je ressens est moins lisible, mais toujours exprimable par hachage.where.not(id: -Float::INFINITY..200)
génèreWHERE (NOT (`users`.`id` <= 200))
etx > 200 == !(x <= 200)
. Cela est nécessaire si l'on devait utiliser le hachage de la syntaxe pour un champ qui n'était pas un entier.Une meilleure utilisation, est de créer un champ dans le modèle de l'utilisateur
where(arel_table[:id].gt(id))
Si vous voulez un plus intuitive de l'écriture, il existe un joyau appelé squeel qui vous permettra d'écrire vos instructions, comme ceci:
Notez le 'accolade' caractères { } et
id
être juste un texte.Tout ce que vous avez à faire est d'ajouter squeel à votre Gemfile:
Cela peut faciliter votre vie beaucoup lors de l'écriture complexe de l'instruction SQL en Ruby.
Arel est votre ami.
J'ai souvent ce problème avec les champs de date (où les opérateurs de comparaison sont très courants).
À élaborer davantage sur Mihai réponse, qui je crois est une solide approche.
Pour les modèles, vous pouvez ajouter des étendues comme ceci:
... et puis dans votre contrôleur, ou n'importe où en utilisant votre modèle:
... un exemple plus complexe avec des jointures ressemble à ceci:
Un énorme avantage de cette approche est (un), il vous permet de composer vos requêtes à partir de différentes portées et (b) évite alias collisions lorsque vous vous joignez à deux fois la même table depuis arel_table va gérer cette partie de la génération de requêtes.
Plus courte:
where("id > ?", 200)
syntaxe). Ce n'est pas d'atteindre cet objectif.