2009-09-03 13 views

risposta

40

Non c'è built-in ActiveRecord validatore per DateTimes, ma è possibile aggiungere facilmente questo tipo di capacità di un modello di ActiveRecord, senza l'utilizzo di un plugin, con qualcosa di simile:

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 
+0

Perfetto, grazie Gabe. – Daniel

+0

Sono contento che questo sia stato d'aiuto. Non è il codice più glorioso, ma funziona. –

+0

Grazie, è grandioso. Ho provato "validates_timeliness" ma ho riscontrato problemi con getter e setter. Questo ha funzionato perfettamente. –

-2

E 'piuttosto necessario per validare date. Con gli helper del modulo Rails predefinito è possibile selezionare date come il 31 settembre. risposta

+0

Convalidare l'input dell'utente tramite i moduli è un buon inizio, ma il contesto della domanda suggerisce che l'OP stava chiedendo delle convalide del modello di Rails. –

12

di Gabe non ha funzionato per me, ecco quello che ho fatto per convalidare le mie date:

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 

Stavo solo cercando di convalidare che la data è in realtà una data, e non una stringa, carattere, int, float, ecc ...

Più complesso convalida della data può essere trovato qui: https://github.com/codegram/date_validator

+1

La gemma è la soluzione più semplice, mi ci sono voluti tre minuti per l'implementazione. Non ne vale la pena scrivere un codice. –

+2

@MichaelSchmitz - Vale la pena scrivere il codice perché il codice è auto-esplicativo - le nuove persone che guardano il codice potrebbero non sapere dell'esistenza di queste gemme e aggiunge un sovraccarico extra per quello che è un compito semplice. – Toby

+0

@Toby: grazie per il puntatore, hai ragione su questo. Per ora sono l'unico sviluppatore, suppongo di essere felice che funzioni. –

1

È possibile creare un validatore datetime personalizzato da soli

1) Creare una cartella denominata validatori nella all'interno app directory

2) creare un file datetime_validator.rb. con il seguente contenuto all'interno app/validatori directory

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) Applicare questa convalida del modello

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

4) Aggiungere la seguente riga nel application.rb

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

5) Restart l'applicazione rotaie

Nota: il metodo sopra testato su rotaie 4

6

Le versioni recenti di Rails saranno valori type cast prima della convalida, pertanto i valori non validi verranno passati come nil ai validatori personalizzati. Sto facendo qualcosa di simile:

# 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