Rails Хронический камень не проверяется, как ожидалось
Я пытаюсь ввести дату '03/20/1985'в текстовое поле с именем "день рождения" и вставить его в поле базы данных с типом столбца "дата".
Когда я вхожу 10/20/1985
я получаю сообщение об ошибке "День рождения недействителен", но когда я вхожу 20/10/1985
, это работает просто отлично.
Из всей документации, которую я читал, хронический должен анализировать '10/20/1985' как mm / dd / yyyy, но кажется, что он анализирует его как dd/mm/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
2 ответа
Если значение хранится в базе данных как дата, Rails будет приводить значение из строки к дате Ruby при назначении. Я думаю, что, вероятно, использует встроенный Date.parse
метод ( документы):
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
В таком случае, вы хотите избежать принуждения и получить в руки грубую строку, чтобы разобраться с Chronic. Это идеальный вариант использования для виртуальных атрибутов. Есть несколько способов сделать это, что-то вроде этого должно помочь вам начать
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
,
Оба работают на меня, может быть, вам нужно обновление.
Также:
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