web-dev-qa-db-fra.com

rails construit en validation datetime

Est-ce que Rails effectue une validation pour datetime? J'ai trouvé un plugin http://github.com/adzap/validates_timeliness/tree/master , Mais il semble que quelque chose devrait sortir de la boîte.

30
Daniel

Il n'y a pas de validateur ActiveRecord intégré pour DateTimes, mais vous pouvez facilement ajouter ce type de fonctionnalité à un modèle ActiveRecord, sans utiliser de plugin, avec quelque chose comme:

class Thing < ActiveRecord::Base
  validate :happened_at_is_valid_datetime

  def happened_at_is_valid_datetime
    errors.add(:happened_at, 'must be a valid datetime') if ((DateTime.parse(happened_at) rescue ArgumentError) == ArgumentError)
  end
end
41
Gabe Hollombe

La réponse de Gabe n'a pas fonctionné pour moi, alors voici ce que j'ai fait pour valider mes dates:

class MyModel < ActiveRecord::Base
  validate :mydate_is_date?

  private

  def mydate_is_date?
    if !mydate.is_a?(Date)
      errors.add(:mydate, 'must be a valid date') 
    end
  end
end

Je cherchais juste à valider que la date est en fait une date, et non une chaîne, un caractère, un int, un float, etc.

Une validation de date plus complexe peut être trouvée ici: https://github.com/codegram/date_validator

12
Sauce McBoss

Les versions récentes de Rails seront saisiront les valeurs avant la validation. Ainsi, les valeurs non valides seront passées sous la forme nils aux validateurs personnalisés. Je fais quelque chose comme ça:

# app/validators/date_time_validator.rb
class DateTimeValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    if record.public_send("#{attribute}_before_type_cast").present? && value.blank?
      record.errors.add(attribute, :invalid)
    end
  end
end
# app/models/something.rb
class Something < ActiveRecord::Base
  validates :sold_at, date_time: true
end
# spec/models/something_spec.rb (using factory_girl and RSpec)
describe Something do
  subject { build(:something) }

  it 'should validate that :sold_at is datetimey' do
    is_expected.not_to allow_value(0, '0', 'lorem').for(:sold_at).with_message(:invalid)
    is_expected.to allow_value(Time.current.iso8601).for(:sold_at)
  end
end
7
Halil Özgür

Vous pouvez créer vous-même un validateur datetime personnalisé 

1) créer un dossier appelé validateurs dans le répertoire interne de l'application

2) créez un fichier datetime_validator.rb. avec le contenu suivant dans le répertoire app/validators

 class DatetimeValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    if ((DateTime.parse(value) rescue ArgumentError) == ArgumentError)  
      record.errors[attribute] << (options[:message] || "must be a valid datetime")
    end
  end
end

3) Appliquer cette validation sur le modèle

class YourModel < ActiveRecord::Base
  validates :happend_at, datetime: true
end

4) Ajoutez la ligne ci-dessous dans application.rb

config.autoload_paths += %W["#{config.root}/app/validators/"]

5) Redémarrez votre application Rails 

Remarque: la méthode ci-dessus testée dans Rails 4

Je recommande un joyau date_validator. Voir https://rubygems.org/gems/date_validator . Il est bien entretenu et son API est simple et compacte.

0
Tsutomu