2012-11-09 42 views
4

我試圖在名爲「birthday」的文本字段中輸入日期'03/20/1985',並將其插入到列類型爲「date」的數據庫字段中。Rails慢性寶石沒有按預期驗證

當我輸入10/20/1985時,出現錯誤「生日無效」,但是當我輸入20/10/1985時,它工作得很好。

從我一直在閱讀的所有文檔中,chronic應該將mm/dd/yyyy解析爲'10/20/1985',但它似乎將其解析爲dd/mm/yyyy。

我該如何解析日期爲mm/dd/yyyy?

/models/user.rb

class User < ActiveRecord::Base 
    # Include default devise modules. Others available are: 
    # :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable 
    devise :database_authenticatable, :registerable, 
     :recoverable, :rememberable, :trackable, :validatable, :authentication_keys => [:login] 

    # Virtual attribute for authenticating by either username or email 
    # This is in addition to a real persisted field like 'username' 
    attr_accessor :login 

    # Setup accessible (or protected) attributes for your model 
    attr_accessible :email, :password, :password_confirmation, :remember_me, :username, :login, :first_name, :last_name, :home_phone, :cell_phone, :work_phone, :birthday, :home_address, :work_address, :position, :company 

    validate :birthday_is_date 
    validate :position, :presence => true 

    require 'chronic' 

    # validate the birthday format 
    def birthday_is_date 
    errors.add(:birthday, "is invalid") unless Chronic.parse(birthday) 
    end 

    # validates email or username when logging in 
    def self.find_first_by_auth_conditions(warden_conditions) 
    conditions = warden_conditions.dup 
    if login = conditions.delete(:login) 
     where(conditions).where(["lower(username) = :value OR lower(email) = :value", { :value => login.downcase }]).first 
    else 
     where(conditions).first 
    end 
    end 

end 
+0

數據庫中的值是什麼樣的? –

+0

如果我使用'20/10/1985'分貝顯示'2012-10-20',但如果我使用'10/20/1985',沒有任何更新到數據庫,我收到錯誤消息。 – Catfish

+0

不知道是否重要,但這是一個設計模型 – Catfish

回答

3

如果該值存儲在數據庫中的日期,Rails會強制從字符串到分配的Ruby的日期值。我認爲它可能使用內置的Date.parse法(docs):

Date.parse "2012-10-20" 
# => #<Date 2012-10-20 ...> 

Date.parse "20-10-2012" 
# => #<Date 2012-10-20 ...> 

Date.parse "10-20-2012" 
# => ArgumentError: invalid date 

既然如此,你想避免脅迫,讓你的手在一個原始字符串慢性解析。這是virtual attributes的理想用例。還有你可以做一些方法,這樣的事情應該讓你開始

class User < ActiveRecord::Base 
    validate :birthday_is_date 

    # an explicit implementation 
    def birthday_string 
    if @birthday_string 
     @birthday_string 
    elsif birthday.present? 
     birthday.strftime("%d-%m-%Y") 
    else 
     "" 
    end 
    end 

    # a shorter implementation 
    def birthday_string 
    @birthday_string || birthday.try(:strftime, "%d-%m-%Y") 
    end 

    def birthday_string=(value) 
    @birthday_string = value 
    self.birthday = parse_birthday 
    end 

    private 

    def birthday_is_date 
    errors.add(:birthday_string, "is invalid") unless parse_birthday 
    end 

    def parse_birthday 
    Chronic.parse(birthday_string) 
    end 
end 
在表單中

然後用birthday_string,而不是birthday

+0

這個效果很好,除了當我輸入'1/5/1980'的日期(1980年1月5日)時,它將它作爲'1980-05-01'保存到數據庫,然後在我的應用中顯示爲'05/01/1980'。我怎麼能這樣做,所以它明白,我想要1/5/1980實際上意味着1980年1月5日,而不是1980年5月1日? – Catfish

+0

其實它現在似乎在工作。我注意到在日誌中有一個關於無法批量分配birthday_string的警告,所以我加了:birthday_string to attr_accessible,現在它工作的很好。 – Catfish

+0

我剛剛注意到的一件事是,如果一個生日是空的,我的編輯頁面會用'未定義的方法'strftime''爆炸。你知道我可以如何避免這個錯誤與空生日? – Catfish

1

對我來說這兩個工作,也許你需要更新。

另外:

Chronic.parse '2/10/1985' 
#=> 1985-02-10 12:00:00 +0800 
Chronic.parse '2/10/1985', :endian_precedence => :little 
#=> 1985-10-02 12:00:00 +0800 
+0

我有版本0.8.0。我應該更新什麼? – Catfish

+0

如果我只是使用導軌控制檯,它也適用於我。 – Catfish

+0

也許不是那麼。這可能是一個場所,但我不確定。 – pguardiario