2010-08-17 47 views
8

我在一个表单内视date_select,但是在提交返回的值是一个哈希的形式,像这样:如何将从rails中的date_select返回的哈希值转换为Date对象?

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

我怎么可以转换到在轨日期格式,所以我可以使用它作为查询数据库时的一个条件,例如:condition => {:dates == :some_date_from_date_select}?我试着打电话Date.parse(:some_date_from_date_select),但它没有工作,因为它期待一个字符串,而不是一个哈希映射。

是否有轨道的方式来做到这一点?

感谢

回答

9

我不知道一轨的方式,但这种 “单行程序” 的伎俩:

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" 

或者附魔少:

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

英雄,谢谢 – 2010-08-17 20:51:36

0

可以从lib/active_record/connection_adapters/abstract/schema_definitions.rb(行号67开始)(即方法type_cast)跟踪此特定代码(执行转换的代码)。

这两种方法用于从字符串的日期:

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

我对这个

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

是哈希的元素的顺序放心?这段代码似乎取决于此。 – navjotk 2013-02-20 18:41:57

+0

散列顺序确保在红宝石1.9,但不是在1.8.7 – 2013-05-08 10:18:50

1

很短的一个在线解决方案这里有一个通用的方法来做到这一点,同时也支持部分日期/时间和空字段:

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 

示例使用:

# 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

您的示例没有为我工作..但我切换: Date.new(*部分)Time.zone.now(parts.join( “/”)),那么它效果很好 – 2013-08-08 18:54:40

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

注:工作在红宝石1.9.2+,因为它取决于哈希表元素的顺序。

两个东西在这里:

相关问题