2013-09-22 76 views
0

確定一個日期字符串,所以有一堆相關主題的答案,但出於某種原因,似乎沒有人有興趣在以下極現實的問題:如何驗證Rails中

我有一個Timecard型號,與to_datefrom_date字段。我使用的是jquery.ui.datepicker,一般來說 - 一切都很好。我還使用了「validates_timeliness」寶石:

class Timecard < ActiveRecord::Base 
    ... 
    validates_date :to_date 
    validates_date :from_date 
    ... 
end 

然而,如果用戶決定手動編輯的文本字段,進入類似1929 -Feb-2013' (這是一個無效的日期),這日期將被轉換爲'01-Mar-2013'。下面的規格將失敗:

describe "POST #create" do 
    ... 
    context "with invalid attributes (invalid date)" do 
    it "re-renders the :new template" do 
     timecard = fix_date_attribs_for(:timecard_feb) 
     # Manually create an invalid date in the params hash - Feb only has 28 days 
     timecard['to_date(3i)'] = 29 
     post :create, timecard: timecard 
     response.should render_template :new 
    end 
    end 
    ... 
end 

以下putstimecards_controller.rb

.>>>> true - --- !ruby/object:Timecard 
attributes: 
    id: 
    name: February 2013 
    from_date: 2013-02-01 
    to_date: 2013-03-01 
    created_at: 
    updated_at: 
F 

Failures: 

    1) TimecardsController POST #create with invalid attributes (invalid date) re-renders the :new template 
    Failure/Error: response.should render_template :new 
     expecting <"new"> but rendering with <[]> 
    # ./spec/controllers/timecards_controller_spec.rb:65:in `block (4 levels) in <top (required)>' 

Finished in 0.28495 seconds 
17 examples, 1 failure 

我如何:

def create 
    @timecard = Timecard.new(timecard_params) 
    puts ">>>> #{@timecard.valid?} - #{@timecard.to_yaml}" 
    ... 
end 

運行上面的規格時,將產生以下輸出在這裏做輸入驗證?在模型中使用回調看起來太離譜了(因爲問題發生之前 - 當控制器執行@timecard = Timecard.new(timecard_params)時)。我可以嘗試在控制器中捕獲Date.new(relevant_timecard_params)異常,但它無法訪問errors散列,因此我無法告訴用戶這是一個無效日期,更不用說控制器聽起來不像正確的地方做輸入驗證...請幫助...

更新1

隨着「validate_timeliness」作爲@Grantovich以下建議(啓用插件)和saveupdate失敗,無效的日期,如'29 -Feb-2013',即使沒有在模型中寫入validates_date :to_date。當添加validates_datesaveupdate失敗,並且驗證字段被設置爲nil,即使是完全有效的輸入(通過驗證邏輯,我懷疑)。

還試過指定格式:validates_date :to_date, format: 'dd-mmm-yyyy'但得到了相同的結果。

+0

BTW,我忘了提及,但目前該表格不會保存糟糕的'29 -Feb-2013'日期。只是它不會向用戶顯示任何消息,也不是可測試的。 – Yaya

回答

2

您看到的行爲來自標準的Ruby時間解析器,默認情況下使用validates_timeliness。您可以通過Time.parse手動運行你的例子來看看這個:

irb(main):001:0> Time.parse('29-Feb-2013') 
=> 2013-03-01 00:00:00 -0500 

This section of the validates_timeliness README說可選的timeliness解析器是「比Ruby的解析器,這意味着如果它不是一個有效的它不會接受這個月的日子更加嚴格這個月的號碼「。這似乎正是你想要的行爲,所以我想嘗試投入validates_timeliness.rb初始化以下(或增加的配置行,如果你已經有一個):

ValidatesTimeliness.setup do |config| 
    config.use_plugin_parser = true 
end 
+1

我建議在日期/時間解析器之後應用救援來避免異常'Time.parse('35 -Feb-2013')rescue nil' – gotva

+0

我已經刪除了'validates_timeliness'gem,並且更改了我的表單以本地化日期存在: <%= f。text_field:from_date,:class =>'datepicker', \t \t \t \t:value => @ timecard.from_date.nil? ?零:L(@ timecard.from_date)%> 錯誤的日期,現在無效(和驗證:驗證存在,他們說:「不能爲空)。 – Yaya

+0

OK,回來‘validates_timeliness’(刪除它留下的東西在現在的問題是rspec示例失敗 – Yaya