J'ai plusieurs modèles avec un attribut de date et pour chaque modèle, je voudrais valider ces dates contre une plage donnée. Un exemple de base serait:
validates_inclusion_of :dated_on, :in => lambda {{ (Date.today - 2.years)..(Date.today + 2.years)}}
7 Réponses :
Si la validation est la même pour chaque classe, la réponse est assez simple: placez une méthode de validation dans un module et mélangez-la dans chaque modèle, puis utilisez Si vous voulez différentes gammes pour chaque modèle, vous voulez probablement quelque chose de plus comme ceci: p> valider code> pour ajouter la validation: < Pré> xxx pré>
Merci, c'est utile mais je viens de modifier ma question pour améliorer l'explication. Je suis idéalement à la recherche d'une solution plus générique que je peux utiliser sur des modèles et pour tout champ de date donné.
J'ai mis à jour cette solution pour correspondre plus de plus près au cas d'utilisation mise à jour, mais je préfère loin ma solution.
Une solution différente consiste à compter sur le fait que valideated_inclusion_of code> nécessite uniquement un objet
: dans code> objet qui répond à
inclure? code>. Construisez une plage d'évaluation retardée comme suit:
class DelayedEvalRange
def initialize(&range_block)
@range_block = range_block
end
def include?(x)
@range_block.call.include?(x)
end
end
class FirstModel
validates_inclusion_of :dated_on, :in => (DelayedEvalRange.new() { ((5.years.ago)..(5.years.from_now)) })
end
Vous pouvez utiliser validateur de date :
Considérez que votre modèle deviendra soudainement invalide après 2 ans.
Demandez-vous si vous devez évaluer la plage au moment de l'exécution. Un bon développeur ne va pas toujours pour l'exactitude, si le prix est la complexité, IMHO. p>
Je voulais vérifier que la mentale, une date était raisonnable, c'est-à-dire quelques années à partir de maintenant. Peu importe que cela s'avère être une gamme de plusieurs années d'aujourd'hui ou il y a deux semaines, et mes processus de serveur ne sont pas susceptibles de courir dans quelques années. En fin de compte, j'ai décidé que la solution plus simple (juste une inclusion directe: In => raisonnable_date_range) a été préférable à une solution correcte, mais plus compliquée. P>
Cela dit, j'aime la solution de James A. Rosen avec RetardeDevalrange. Si votre gamme n'est que quelques jours, ou la correction est importante pour une autre raison, j'irais avec cela. P>
Validate: Future_Date, Inclusion: {in: -> (g) {(date.tomorrow..float :: Infinity)} code> p> P>
La solution la plus simple pour moi était la suivante: Toutefois, si vous souhaitez supprimer des duplications, je suggère de le déplacer dans votre propre validateur . p> et oui, je veux exécuter l'exécution d'exécution car mon code sera em> exécuter Dans quelques années, et après plus d'un an, je n'ai pas été déployé, je ne veux sûrement pas aborder le projet. P> p>
La solution la plus simple et la solution de travail consiste à utiliser la validation intégrée des rails. Il suffit de le valider comme ça: Si vous devez valider la présence également, ajoutez simplement une autre validation: p> rappelez-vous que vous pouvez Toujours utiliser des aides comme Un soin particulier doit être pris lors de l'utilisation des dates relatives . Considérez l'exemple suivant où l'âge doit être compris entre 18..65: P> une personne qui est Cela pourrait conduire à de nombreux cas inattendus, où votre modèle ne peut plus être mis à jour car cette validation échoue. P> Un moyen intelligent de gérer ce cas est de valider le champ uniquement lorsqu'il change effectivement: P> 1.day.ago code> ou
1.Year.from_now code> pour définir les gammes. p>
valide? # => vrai code> aujourd'hui, deviendra soudainement invalide une fois qu'ils deviennent 66. P>
validates :birthdate,
inclusion: { in: 65.years.ago..18.years.ago },
if: ->(model) { model.birthdate.present? && model.birthdate_changed? }