2010-08-17 18 views
8

Tengo un date_select en mi opinión dentro de un formulario, sin embargo, al enviar, el valor devuelto está en una forma de hash de este modo:cómo convertir un valor hash devuelto desde un date_select en rieles a un objeto Date?

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

¿Cómo puedo convertir que, en un formato de fecha en los carriles para que pueda utilizar como una condición al consultar la base de datos, por ejemplo, :condition => {:dates == :some_date_from_date_select}? Intenté llamar al Date.parse(:some_date_from_date_select), pero no funcionó porque esperaba una cadena y no un mapa hash.

¿hay alguna manera de hacer esto?

gracias

Respuesta

9

No sé acerca de una forma carriles, pero esto "de una sola línea" hace el truco:

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" 

O, con menos mágica:

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

héroe, gracias a que –

0

Este código en particular (el que realiza la conversión) se puede rastrear desde lib/active_record/connection_adapters/abstract/schema_definitions.rb, línea no 67 en adelante, es decir, el método type_cast.

Estos dos métodos se utilizan para generar una fecha de cadena:

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

tengo una solución a corto una línea para este

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

es el orden de los elementos de un hash aseguraba esto? Este código parece depender de eso. – navjotk

+0

el orden de hash está garantizado en ruby ​​1.9, pero no en 1.8.7 –

1

Aquí está una manera genérica para hacerlo, que también es compatible fechas parciales/tiempos y los campos vacíos: uso

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 

ejemplo:

# 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

Su ejemplo no funcionó para mí ... pero cambié: Date.new (* parts) a Time.zone.now (parts.join ("/")) luego funcionó muy bien –

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

Nota: Funciona en rubí 1.9.2+ ya que depende del orden de los elementos de patata.

dos golosinas aquí:

Cuestiones relacionadas