J'ai une application qui implique des enregistrements d'absence pour les employés.
Je dois vous assurer que les dates de début et de fin pour chaque enregistrement ne se chevauchent pas. P>
SO, par exemple, si je suis entré dans un Enregistrement d'absence qui a commencé aujourd'hui et s'est terminé demain, il ne devrait pas être possible d'entrer une autre à l'intérieur de cette plage de date de quelque manière que ce soit. Donc, je ne pouvais pas en faire un qui commence la veille aujourd'hui, puis se termine la journée après demain, ou une date ultérieure. P>
Pour le mettre simplement, je dois faire la plage de date unique. P >
Quelle est la meilleure façon d'y parvenir? p>
validateurs personnalisés dans la classe modèle qui implique itération à travers tous les enregistrements prennent beaucoup trop de temps à compléter, et je n'ai pas trouvé de gemmes qui abordent cette adresse problème. Je n'ai pas non plus trouvé aucun moyen de périmé par l'unicité dans le modèle non plus. Je suis excentré: / p>
Merci pour votre temps! P>
EDIT: P>
class Absence < ActiveRecord::Base attr_accessible :date, :date_ended, :status, :reason, :form, :user_id, :tempuser, :company_id belongs_to :user default_scope { where(company_id: Company.current_id) } validates :date, :date_ended, :status, :reason, :form, :user_id, presence: true validates_numericality_of :user_id, :only_integer => true, :message => "can only be whole number." end
5 Réponses :
J'utilise ceci:
scope :overlaps, ->(start_date, end_date) do where "(DATEDIFF(start_date, ?) * DATEDIFF(?, end_date)) >= 0", end_date, start_date end def overlaps? overlaps.exists? end # Others are models to be compared with your current model # you can get these with a where for example def overlaps siblings.overlaps start_date, end_date end validate :not_overlap def not_overlap errors.add(:key, 'message') if overlaps? end # -1 is when you have a nil id, so you will get all persisted user absences # I think -1 could be omitted, but did not work for me, as far as I remember def siblings user.absences.where('id != ?', id || -1) end
Pourriez-vous expliquer ce que ces frères et sœurs étaient utilisés dans l'exemple précédent? Et comment va-t-il réellement utiliser votre étendue de chevauchements? Juste en validant le caractère unique des deux dates de la portée des chevauchements?
Voulez-vous pas plus d'une absence d'une période donnée pour un utilisateur donné? va mettre à jour en supposant cela.
Oui, chaque utilisateur ne doit être autorisé qu'à un enregistrement d'absence du 1/1/2013 à, par exemple, 10/1/2013. Toutes les dates entre ces dates sont hors limites pour tout autre record d'absence, pour cet utilisateur.
Je reçois une "méthode non définie" clé? ' Pour Nil: Nilclass "Erreur et" Vous devez fournir au moins une validation "sur" Validatedate: NOT_Overlap ". Qu'est-ce que c'est exactement un frère de fraîcheur au fait? Je pourrais peut-être contribuer davantage si je savais. Je suis loin d'être un expert sur la scope, ha! Edit: Ah, je vois que vous définissez cela dans le nouveau code. À votre santé!
remplacer: la touche avec: base, les frères et sœurs sont des frères et sœurs d'une absence, ce qui signifie des absences du même utilisateur, à l'exception de l'absence actuelle
Il se plaint toujours d'avoir besoin d'au moins une validation sur «Validate: Not_overlap». La méthode non définie était que cela ne savait pas quel était le "utilisateur", mais j'ai réparé celui-là.
La portée par défaut pourrait-elle être en quelque sorte causer ce problème? Cela ne devrait pas, puisque tous mes enregistrements ont des données de scorage correctes
Ignorer mon commentaire précédent, et je pense que cela devrait être validé, ne pas valider le: Not_overlap?
Maintenant, c'est un problème de sqlite ... ça ne sait pas ce qu'est la datrodiff. Serait LISTS.ADEWALL.COM/Archive/trac/2005-may/003124 .html travail à la place?
Voir cette question Stackoverflow.com/questions/5972163/sqlite-query-Questions
Pas d'inquiétude homme, je l'ai obtenue en remplaçant le SQL dans la portée des chevauchements avec ceci: où "((((date julianday (date (date)) - Julianday (((date ((date)) - Julianday ( DATE_LIQUÉ))))> = 0 ", Date_Le Date, Date Merci de toute l'aide, peu de personnes ne passeraient pas trois heures à aider un étranger complet. Si je peux rembourser la faveur, faites le moi savoir! Bonne chance!
UTILISATEUR.ABENDENCES.LOWE.NOT (ID: ID) CODE> générera une déclaration correcte, pas besoin de -1. Nécessite des rails 4 cependant.
Modification de la réponse acceptée, voici une étendue de chevauchements qui fonctionnera pour DBS qui ne comprennent pas la datrodiff ceci dessine sur la solution pour Determine si deux chaînes de date se chevauchent p> p>
Honnêtement, en utilisant > = code> et
<= code> semble plus lisible et portable que
datrodiff code> Même si votre dB prend en charge code> datrodiff code> .
Il y a un gemme appelé validateate_overlap qui vous permet de valider facilement les chevauchements de la plage de date. Vous pouvez également utiliser des étendues sur la validation. P>
Bien que la solution Juanpastas est correcte, elle sera valide pour la création d'enregistrements, mais peut conduire à de fausses validations négatives sur les mises à jour.
Si vous devez modifier un enregistrement existant, dites que la plage est 2014-03-13..2014-06-12 et vous souhaitez le réduire à 2014-03-13..2014-04-12, vous " ll Obtenez une erreur de chevauchement car il vérifie elle-même. P>
def siblings Absence_users.where('user_id = ? AND id != ?', user_id, self) end
Utilisez le gem validateate_overlap code>
.
class Meeting < ActiveRecord::Base belongs_to User validates :start_date, :end_date, overlap: { scope: 'user_id', message_content: 'overlaps with Users other meetings.' } end
Éventuellement en créant un modèle pour enregistrer les dates d'occasion? Quelque chose comme employéeaccendedated. Cela serait plus rapide que d'itération de tous les enregistrements.