95 votes

Comment valider une date dans les rails ?

Je veux être en mesure de valider une date dans mon modèle en ruby on rails. Cependant, le jour, le mois et l'année des valeurs sont déjà convertis en une date incorrecte par le temps qu'ils arrivent à mon modèle.

Par exemple, si j'entre février 31 mars 2009, à mon avis, quand je fais du Modèle.nouveau(params[:modèle]) dans mon contrôleur, il la convertit au 3 Mars 2009. Qui mon modèle voit alors comme une date valide, qui c'est, mais c'est la date incorrecte.

Je voudrais être capable de faire cette validation dans mon modèle. Est-il possible que je peux, ou je suis aller sur ce complètement faux?

J'ai trouvé ce post qui traite de ce problème, mais ne l'a jamais une résolution.

64voto

Jack Chu Points 3795

Je devine que vous êtes à l'aide de l' date_select helper pour générer les balises pour la date. Une autre façon de le faire est d'utiliser sélectionnez le formulaire d'assistance pour les jour, mois, année). Comme ceci (exemple que j'ai utilisé est le created_at champ date):

<%= f.select :month, (1..12).to_a, selected: @user.created_at.month %>
<%= f.select :day, (1..31).to_a, selected: @user.created_at.day %>
<%= f.select :year, ((Time.now.year - 20)..Time.now.year).to_a, selected: @user.created_at.year %>

Et dans le modèle, vous validez la date:

attr_accessor :month, :day, :year
validate :validate_created_at

private

def convert_created_at
  begin
    self.created_at = Date.civil(self.year.to_i, self.month.to_i, self.day.to_i)
  rescue ArgumentError
    false
  end
end

def validate_created_at
  errors.add("Created at date", "is invalid.") unless convert_created_at
end

Si vous êtes à la recherche d'un plugin solution, j'avais la caisse de la validates_timeliness plugin. Il fonctionne comme ceci (à partir de la page github):

class Person < ActiveRecord::Base
  validates_date :date_of_birth, on_or_before: lambda { Date.current }
  # or
  validates :date_of_birth, timeliness: { on_or_before: lambda { Date.current }, type: :date }
end 

La liste des méthodes de validation sont disponibles comme suit:

validates_date     - validate value as date
validates_time     - validate value as time only i.e. '12:20pm'
validates_datetime - validate value as a full date and time
validates          - use the :timeliness key and set the type in the hash.

20voto

Roger Points 121

À l’aide de la gemme chronique :

18voto

Txus Points 141

Si vous voulez 3 Rails ou ruby 1.9 compatibilité try date_validator pierre précieuse !

12voto

joshuacronemeyer Points 681

Enregistrement actif vous donne _before_type_cast les attributs qui contiennent les données d’attribut brut avant le cast de type. Cela peut être utile pour renvoyer les messages d’erreur avec pré valeurs de type cast ou tout simplement faire des validations qui ne sont pas possibles après conversion de type. J’ai se détourneront de suggestion de Daniel Von Fange de la substitution de l’accesseur, parce que faire la validation dans un accesseur modifie le contrat de l’accesseur légèrement. AR est une fonction explicite pour cette situation. L’utiliser. :)

4voto

Daniel Von Fange Points 2739

Étant donné que vous devez gérer la chaîne de date avant sa conversion à une date dans votre modèle, je serait substituer l’accesseur pour ce champ

Disons que la date de votre domaine est « published_date ». Ajouter ceci à votre modèle objet :

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X