Ruby on rails 未按预期进行验证

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 #

我试图将日期'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
  # 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
方法中检查nil
birth
。我已经为我的答案添加了几种可能的方法。
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