当使用Rails date_select with:prompt => true时,我在提交表单时看到一些非常奇怪的行为,但没有选择所有字段 . 例如 .
提交包含1月份但在默认提示下留下的日期和年份字段的表单会导致1月1日0001传递给模型验证 . 如果验证失败并再次呈现表单,则仍会选择1月(正确),但日期设置为1(不正确) . 如果表单仅与所选年份一起提交,则将月份和日期设置为1 .
这是一种非常奇怪的行为 - 任何人都可以给我一个解决方法吗?
问题与多参数分配有关 . 基本上,您希望将三个值存储到一个属性中(即 written_at ) . date_select将此作为 { 'written_at(1)' => '2009', 'written_at(2)' => '5', 'written_at(3)' => '27' } 发送到控制器 . 活动记录将这三个值打包成一个字符串,并用它初始化一个新的Date对象 .
written_at
{ 'written_at(1)' => '2009', 'written_at(2)' => '5', 'written_at(3)' => '27' }
问题始于Date尝试使用无效日期 Date.new(2009, 0, 1) 实例化它时引发异常的事实 . Rails捕获该错误并改为实例化Time对象 . Rails中具有时区支持的Time类具有各种魔力,使其无法使用无效数据 . 这使你的一天变为1 .
Date.new(2009, 0, 1)
在此过程中,活动记录会丢失原始值哈希值,因为它将 written_at stuff填充到数组中并尝试从中创建Date或Time对象 . 这就是表单无法使用 written_at_before_time_cast 方法访问它的原因 .
written_at_before_time_cast
解决方法是在模型中添加六种方法: written_at_year , written_at_year= 和 written_at_year_before_type_cast (年,月,日) . before_validation 过滤器可以重建日期并将其写入write_at .
written_at_year
written_at_year=
written_at_year_before_type_cast
before_validation
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
1 回答
问题与多参数分配有关 . 基本上,您希望将三个值存储到一个属性中(即
written_at
) . date_select将此作为{ 'written_at(1)' => '2009', 'written_at(2)' => '5', 'written_at(3)' => '27' }
发送到控制器 . 活动记录将这三个值打包成一个字符串,并用它初始化一个新的Date对象 .问题始于Date尝试使用无效日期
Date.new(2009, 0, 1)
实例化它时引发异常的事实 . Rails捕获该错误并改为实例化Time对象 . Rails中具有时区支持的Time类具有各种魔力,使其无法使用无效数据 . 这使你的一天变为1 .在此过程中,活动记录会丢失原始值哈希值,因为它将
written_at
stuff填充到数组中并尝试从中创建Date或Time对象 . 这就是表单无法使用written_at_before_time_cast
方法访问它的原因 .解决方法是在模型中添加六种方法:
written_at_year
,written_at_year=
和written_at_year_before_type_cast
(年,月,日) .before_validation
过滤器可以重建日期并将其写入write_at .