2010-08-17 66 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+,因爲它取決於哈希表元素的順序。

兩個東西在這裏:

相關問題