Ruby on rails Rails:验证是否选择了日期\u select中的所有字段,但仍将:prompt设置为true

Ruby on rails Rails:验证是否选择了日期\u select中的所有字段,但仍将:prompt设置为true,ruby-on-rails,Ruby On Rails,当使用railsdate_select with:prompt=>true时,在提交表单时,如果没有选择所有字段,我会看到一些非常奇怪的行为。例如 提交选中了“一月”的表单,但保留在默认提示下的“日期”和“年份”字段将导致在0001年1月1日传递给模型验证。如果验证失败并再次呈现表单,则仍然选择1月(正确),但日期设置为1(错误)。如果提交表单时只选择了年份,则月和日都将设置为1 这是一个非常奇怪的行为-有人能给我一个解决方法吗?这个问题与多参数赋值有关。基本上,您希望将三个值存储到一个属性中(

当使用railsdate_select with:prompt=>true时,在提交表单时,如果没有选择所有字段,我会看到一些非常奇怪的行为。例如

提交选中了“一月”的表单,但保留在默认提示下的“日期”和“年份”字段将导致在0001年1月1日传递给模型验证。如果验证失败并再次呈现表单,则仍然选择1月(正确),但日期设置为1(错误)。如果提交表单时只选择了年份,则月和日都将设置为1


这是一个非常奇怪的行为-有人能给我一个解决方法吗?

这个问题与多参数赋值有关。基本上,您希望将三个值存储到一个属性中(即写入)。所选日期将其作为
{'writed_at(1)=>'2009','writed_at(2)=>'5','writed_at(3)=>'27}
发送给控制器。活动记录将这三个值打包成一个字符串,并用它初始化一个新的日期对象

问题开始于这样一个事实,即当您尝试使用无效日期来实例化Date时,Date会引发异常,例如,
Date.new(2009,0,1)
。Rails捕获该错误并实例化一个时间对象。Rails中支持时区的Time类具有各种各样的魔力,可以使它不使用无效数据。这会让你的一天变成一天

在此过程中,active record会释放原始值散列,因为它将
写入的
内容打包到一个数组中,并试图从中创建日期或时间对象。这就是为什么表单不能再使用
writed\u at\u before\u time\u cast
方法访问它的原因

解决方法是在模型中添加六种方法:
writed\u at_year
writed\u at_year=
,以及
writed\u at_year\u before\u type\u cast
(用于年、月和日)。验证前的
过滤器可以重建日期并将其写入写入

class Event < ActiveRecord::Base
  before_validation :reconstruct_written_at

  def written_at_year=(year)
    @written_at_year_before_type_cast = year
  end

  def written_at_year
    written_at_year_before_type_cast || written_at.year
  end

  def written_at_year_before_type_cast
    @written_at_year_before_type_cast
  end

  private

  def reconstruct_written_at
    written_at = Date.new(written_at_year, written_at_month, written_at_day)
  rescue ArgumentError
    written_at = nil
  end
end
class事件
一个代码示例可能会帮助我们帮助您。谢谢-看起来这就是我要找的,但我必须说,对于这样一个简单而常见的功能来说,这简直是太复杂了!我赞成。这太复杂了。您好,在def writed_at_year=(year)或@writed_at_year=year之前,def writed_at_year中的“year”是什么?这不是写于年吗?我真的不明白这部分(