2010-08-17 14 views
8

Ho un date_select a mio avviso all'interno di un modulo, ma sul presentare il valore restituito è in una forma di hash in questo modo:come convertire un valore di hash restituito da un parametro date_select in un oggetto Date?

{"(1i)"=>"2010", "(2i)"=>"8", "(3i)"=>"16"} 

Come posso convertire che in un formato data data rotaie modo da poter utilizzare è una condizione quando si esegue una query sul database, ad esempio :condition => {:dates == :some_date_from_date_select}? Ho provato a chiamare Date.parse(:some_date_from_date_select) ma non ha funzionato perché si aspettava una stringa e non una mappa hash.

c'è un modo per farlo?

grazie

risposta

9

Non so di un modo rotaie, ma questo "one-liner" fa il trucco:

irb(main):036:0> d = Date.parse({"(1i)"=>"2010", "(2i)"=>"8", "(3i)"=>"16"}.to_a.sort.collect{|c| c[1]}.join("-")) 
=> #<Date: 4910849/2,0,2299161> 
irb(main):037:0> d.to_s 
=> "2010-08-16" 

Oppure, con meno magia:

h={"(1i)"=>"2010", "(2i)"=>"8", "(3i)"=>"16"} 
d=Date.new(h['(1i)'].to_i, h['(2i)'].to_i, h['(3i)'].to_i) 
d.to_s 
=> "2010-08-16" 
+0

eroe, grazie –

0

Questo codice particolare (quello che fa la conversione) può essere rintracciato da lib/active_record/connection_adapters/abstract/schema_definitions.rb, riga n. 67 in poi, cioè il metodo type_cast.

Questi due metodi sono utilizzati per generare una data da stringa:

def fast_string_to_date(string) 
    if string =~ Format::ISO_DATE 
    new_date $1.to_i, $2.to_i, $3.to_i 
    end 
end 

# Doesn't handle time zones. 
def fast_string_to_time(string) 
    if string =~ Format::ISO_DATETIME 
    microsec = ($7.to_f * 1_000_000).to_i 
    new_time $1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i, microsec 
    end 
end 

# Note that ISO_DATE is: 
ISO_DATE = /\A(\d{4})-(\d\d)-(\d\d)\z/ 
2

ho una breve soluzione di una riga per questo

params["due_date"] = {"date(3i)"=>"14", "date(2i)"=>"4", "date(1i)"=>"2014"} 


params["due_date"].map{|k,v| v}.join("-").to_date 
=> Mon, 14 Apr 2014 
+2

è l'ordine degli elementi di un hash Assured? Questo codice sembra dipendere da questo. – navjotk

+0

l'ordine di hash è assicurato in ruby ​​1.9, ma non in 1.8.7 –

1

Ecco un modo generico per farlo, che ha anche supporti date parziali/tempi e campi vuoti: utilizzo

def date_from_date_select_fields(params, name) 
    parts = (1..6).map do |e| 
    params["#{name}(#{e}i)"].to_i 
    end 

    # remove trailing zeros 
    parts = parts.slice(0, parts.rindex{|e| e != 0}.to_i + 1) 
    return nil if parts[0] == 0 # empty date fields set 

    Date.new(*parts) 
end 

Esempio:

# example input: 
# 
# params = { 
# "user": 
#  "date_of_birth(1i)": "2010", 
#  "date_of_birth(2i)": "8", 
#  "date_of_birth(3i)": "16" 
# } 
# } 
date_of_birth = date_from_date_select_fields(params[:user], 'date_of_birth') 
+0

Il tuo esempio non ha funzionato per me .. ma sono passato: Date.new (* parti) a Time.zone.now (parts.join ("/")) poi ha funzionato alla grande –

1
Date.new(*params["due_date"].values.map(&:to_i)) 

Nota: Funziona in Ruby 1.9.2+ poiché dipende l'ordine degli elementi di hash.

Due chicche qui:

Problemi correlati