Ruby on rails 未按预期进行验证
我试图将日期'03/20/1985'输入一个名为“生日”的文本字段,并将其插入一个列类型为“日期”的数据库字段中 当我输入Ruby on rails 未按预期进行验证,ruby-on-rails,ruby,ruby-on-rails-3,chronic,Ruby On Rails,Ruby,Ruby On Rails 3,Chronic,我试图将日期'03/20/1985'输入一个名为“生日”的文本字段,并将其插入一个列类型为“日期”的数据库字段中 当我输入10/20/1985时,我得到错误“生日无效”,但当我输入20/10/1985时,它工作正常 从我所阅读的所有文档中,chronic应该将'10/20/1985'解析为mm/dd/yyyy,但它似乎将其解析为dd/mm/yyyy 如何将日期解析为mm/dd/yyyy /models/user.rb class User < ActiveRecord::Base #
10/20/1985
时,我得到错误“生日无效”,但当我输入20/10/1985
时,它工作正常
从我所阅读的所有文档中,chronic应该将'10/20/1985'解析为mm/dd/yyyy,但它似乎将其解析为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
class用户[:登录]
#用于通过用户名或电子邮件进行身份验证的虚拟属性
#这是对真正持久化字段(如“用户名”)的补充
属性访问器:登录
#设置模型的可访问(或受保护)属性
属性可访问:电子邮件、密码、密码确认、记住我、用户名、登录名、姓氏、家庭电话、手机、工作电话、生日、家庭地址、工作地址、公司
验证:生日是什么日期
验证:位置,:存在=>true
需要“慢性”
#验证生日格式
def生日是什么日子
错误。添加(:birth,“无效”),除非是Chronic.parse(birth)
结束
#登录时验证电子邮件或用户名
定义self.find_first_by_auth_条件(典狱长条件)
条件=典狱长_conditions.dup
如果login=conditions.delete(:login)
where(条件)。where([“lower(username)=:value或lower(email)=:value”,{:value=>login.downcase}])
其他的
在哪里(条件)。首先
结束
结束
结束
两者都适合我,也许你需要更新
此外:
如果该值作为日期存储在数据库中,Rails将在赋值时将该值从字符串强制为Ruby日期。我认为它可能使用内置的
Date.parse
方法():
Date.parse“2012-10-20”
# => #
日期:2012年10月20日
# => #
日期:2012年10月20日
#=>ArgumentError:无效日期
在这种情况下,您希望避免强制,并获得一个原始字符串,以便使用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
class用户
然后在表单中使用
birth\u string
,而不是birth
数据库中的值是什么?如果我使用'20/10/1985',数据库会显示2012-10-20
,但是如果我使用10/20/1985
,数据库不会更新任何内容,我会收到错误消息。不确定这是否重要,但这是一个Desive模型我只是想知道数据库表的构造是否很奇怪,或者是什么,但它似乎是合法的…你在用i18n做什么吗?也许不是。这可能是区域设置的问题,但我不确定。从我的rails控制台到我的实际应用程序有什么不同?可能是环境?听起来有些不同,但我不能说。这很有效,除非当我输入日期1/5/1980
(1980年1月5日),它将其保存到数据库中,作为1980-05-01
,然后在我的应用程序中显示为05/01/1980
。我怎样才能让它明白我想要的1980年1月5日实际上是指1980年1月5日,而不是1980年5月1日?事实上,它现在似乎起作用了。我注意到日志中有一条关于无法批量分配生日字符串的警告,所以我添加了:生日字符串到attr\u accessible,现在效果很好。我刚刚注意到的一件事是,如果生日为null,我的编辑页面就会出现未定义的方法“strftime”
。您知道如何使用null birth避免此错误吗?您只需要在birth\u string
方法中检查nilbirth
。我已经为我的答案添加了几种可能的方法。
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
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