Dov’è il metodo Rails che converte i dati da `datetime_select` in un object DateTime?

Quando usiamo in un modulo, genera HTML come:

  #year  #month  #day  #hour  #minute 

Quando viene inviato quel modulo, vengono ricevuti somedate1(i) valori somedate1(i) :

 {"date1(1i)"=>"2011", "date1(2i)"=>"2", "date1(3i)"=>"21", "date1(4i)"=>"19", "date1(5i)"=>"25"} 

Come posso convertirlo in un object DateTime? Potrei scrivere il mio metodo per farlo, ma dato che Rails è già in grado di fare la conversione, mi chiedevo se potevo chiamare quel metodo Rails per farlo per me.

Il problema è che non so dove cercare quel metodo.

Ps. Alla fine sto cercando di risolvere questo altro problema che ho e questa domanda è il primo passo nel tentativo di trovare una soluzione a quell’altro problema.

L’inizio di quel percorso di codice sembra essere proprio qui:

https://github.com/rails/rails/blob/d90b4e2/activerecord/lib/active_record/base.rb#L1811

Era difficile da trovare! Spero che questo ti aiuti a trovare ciò di cui hai bisogno

Questa conversione avviene all’interno di ActiveRecord quando si salva il modello.

Puoi aggirare il problema con qualcosa di simile:

 somedate = DateTime.new(params["date1(1i)"].to_i, params["date1(2i)"].to_i, params["date1(3i)"].to_i, params["date1(4i)"].to_i, params["date1(5i)"].to_i) 

DateTime::new è un alias di DateTime::civil ( ruby-doc )

Ciao ho aggiunto quanto segue su ApplicationController e fa questa conversione.

  #extract a datetime object from params, useful for receiving datetime_select attributes #out of any activemodel def parse_datetime_params params, label, utc_or_local = :local begin year = params[(label.to_s + '(1i)').to_sym].to_i month = params[(label.to_s + '(2i)').to_sym].to_i mday = params[(label.to_s + '(3i)').to_sym].to_i hour = (params[(label.to_s + '(4i)').to_sym] || 0).to_i minute = (params[(label.to_s + '(5i)').to_sym] || 0).to_i second = (params[(label.to_s + '(6i)').to_sym] || 0).to_i return DateTime.civil_from_format(utc_or_local,year,month,mday,hour,minute,second) rescue => e return nil end end 

Qualcun altro qui ha offerto la soluzione di utilizzare DateTime.new, ma che non funzionerà in Postgresql. Ciò salverà il record così com’è, ovvero, poiché è stato inserito nel modulo, e quindi non verrà salvato nel database come tempo utc, se si utilizza “timestamp senza fuso orario”. Ho passato ore a cercare di capire questo, e la soluzione era usare Time.new piuttosto che DateTime.new:

 datetime = Time.new(params["fuel_date(1i)"].to_i, params["fuel_date(2i)"].to_i, params["fuel_date(3i)"].to_i, params["fuel_date(4i)"].to_i, params["fuel_date(5i)"].to_i) 

Dovevo fare qualcosa di molto simile e ho finito per usare questo metodo:

 def time_value(hash, field) Time.zone.local(*(1..5).map { |i| hash["#{field}(#{i}i)"] }) end time = time_value(params, 'start_time') 

Vedi anche: TimeZone.local

Ho avuto questo problema con Rails 4. Si è scoperto che ho dimenticato di aggiungere i parametri consentiti al mio controller:

 def event_params params.require(:event).permit(....., :start_time, :end_time,...) end 

Questo è il metodo che uso – restituisce le chiavi cancellate come un nuovo hash.

 class Hash def delete_by_keys(*keys) keys.each_with_object({}) { |k, h| h[k] = delete(k) if include? k } end end