ActiveRecord Trouver de Par An, Jour ou Mois, sur un champ de Date
J'ai un ActiveRecord modèle qui dispose d'un attribut de date. Est-il possible d'utiliser cet attribut date à trouver par Année, le Jour et le Mois:
Model.find_by_year(2012)
Model.find_by_month(12)
Model.find_by_day(1)
ou est-il simplement possible de find_by_date(2012-12-1).
J'espérais que je pourrais éviter de créer de l'Année, le Mois et le Jour des attributs.
- Je ne pense pas que j'ai bien communiqué. Ce que je veux faire est d'être en mesure de trouver des enregistrements ou des objets en utilisant la date, l'année, le mois et le jour seulement. Le premier cas est simple, sa au plus tard trois (en utilisant les mois, jour et année) qui m'en difficulté.
Vous devez vous connecter pour publier un commentaire.
En supposant que votre "date de l'attribut" est une date (au lieu d'un timestamp) alors qu'un simple
where
vous donnera votre "recherche par date":Vous ne voulez pas
find_by_date_column
afin d'avoir plus d'un résultat.Pour l'année, le mois et le jour des requêtes vous souhaitez utiliser le
extract
de la fonction SQL:Toutefois, si vous utilisez SQLite, vous auriez à perdre avec
strftime
car il ne sait pas ce queextract
est:La
%m
et%d
les spécificateurs de format va ajouter des zéros dans certains cas et qui peut confondre les tests d'égalité, d'où lecast(... as int)
pour forcer la mise en forme des chaînes de nombres.ActiveRecord de ne pas vous protéger de toutes les différences entre les bases de données, de sorte que dès que vous faites quelque chose de non négligeable, vous devez construire votre propre portabilité de la couche (laid mais il est parfois nécessaire), attachez-vous à un ensemble limité de bases de données (réaliste, à moins que vous publiez quelque chose qui doit fonctionner sur une base de données), ou de faire tout votre logique en Ruby (fou pour tout montant non négligeable de données).
L'année, le mois et le jour du mois de requêtes seront assez lent sur de grandes tables. Certaines bases de données vous permettent d'ajouter des index sur les résultats de la fonction mais ActiveRecord est trop stupide pour comprendre ce qui va faire de gros dégâts si vous essayez de les utiliser; donc, si vous trouvez que ces requêtes sont trop lent, alors vous aurez à ajouter les trois colonnes que vous essayez d'éviter.
Si vous allez à l'aide de ces requêtes beaucoup, alors vous pouvez ajouter des étendues pour eux, mais le recommandé d'ajouter un champ avec un argument est juste pour ajouter une méthode de classe:
Si vous auriez des méthodes de classe qui ressemble à ceci:
CAST
de la date nombre à un nombre entier au lieu d'ajouter des 0 (ajout de 0 m'a donné le mauvais numéro pour une raison quelconque). Mon révisé les filtres sont alors:Model.where("CAST(strftime('%Y', date_column) as INT) = ?", desired_year) Model.where("CAST(strftime('%m', date_column) as INT) = ?", desired_month) Model.where("CAST(strftime('%d', date_column) as INT) = ?", desired_day_of_month)
cast(... as int)
est mieux que la tricherie dans tous les cas, je ne sais pas pourquoi je n'ai pas utilisécast
en premier lieu.TO_CHAR
avecILIKE
en une seule ligne, j'ai posté l'exemple complet à la fin de ce filstrftime
car il ne sait pas ce queextract
est la section" déjà là.De base de données indépendant de la version ...
beginning_of_day
/end_of_day
etbeginning_of_month
/end_of_month
pour les autres implémentations.Dans votre Modèle:
Dans votre Contrôleur:
Pour MySQL essayer
Je pense que la façon la plus simple pour ce faire est l'portée:
L'utiliser comme ceci:
Qui sera de retour tous les modèles avec un date_field entre le début et la fin de la journée pour la date que vous envoyez.
'd >= ? and d < ?', dt.beginning_of_day, dt.tomorrow.beginning_of_day
. À l'aide de<
et>
manque la frontière entre les jours.Essayez ceci:
MONTH
fonction. Essayez d'extraire ou d'date_part. wiki.postgresql.org/wiki/MONTH()_equivalent postgresqltutorial.com/postgresql-date_partSimple de mise en Œuvre pour L'Année
app/models/your_model.rb
Utilisation
J'aime BSB réponse, mais comme un champ d'application
Ce serait une autre:
Fonctionne assez bien pour moi dans SQLite.
Pas besoin de
extract
méthode, cela fonctionne comme un charme dans postgresql:Une autre courte portée comme ci-dessous:
Appel de la portée: