9
votes

Comment valider l'attribut de date d'un modèle sur une plage spécifique (évaluée au moment de l'exécution)

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)}}


0 commentaires

7 Réponses :


7
votes

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 valider pour ajouter la validation: < Pré> xxx

Si vous voulez différentes gammes pour chaque modèle, vous voulez probablement quelque chose de plus comme ceci: xxx


2 commentaires

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.



1
votes

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


0 commentaires

14
votes

Vous pouvez utiliser validateur de date : xxx


1 commentaires

Considérez que votre modèle deviendra soudainement invalide après 2 ans.



0
votes

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.

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.

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.


0 commentaires

3
votes

Validate: Future_Date, Inclusion: {in: -> (g) {(date.tomorrow..float :: Infinity)}


0 commentaires

0
votes

La solution la plus simple pour moi était la suivante: xxx

Toutefois, si vous souhaitez supprimer des duplications, je suggère de le déplacer dans votre propre validateur .

et oui, je veux exécuter l'exécution d'exécution car mon code sera 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.


0 commentaires

1
votes

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: xxx pré>

Si vous devez valider la présence également, ajoutez simplement une autre validation: p> xxx pré>

rappelez-vous que vous pouvez Toujours utiliser des aides comme 1.day.ago code> ou 1.Year.from_now code> pour définir les gammes. p>

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> xxx pré>

une personne qui est valide? # => vrai code> aujourd'hui, deviendra soudainement invalide une fois qu'ils deviennent 66. P>

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>

validates :birthdate, 
          inclusion: { in: 65.years.ago..18.years.ago }, 
          if: ->(model) { model.birthdate.present? && model.birthdate_changed? }


0 commentaires