我遇到日期格式问题。我有一个时间选择器,它有一个时髦的格式的日期(嗯,这是一个很好的格式,实际上,但不是计算机)。我正在尝试Chronic
解析日期,以便可以正确保存。
起初,我在控制器的创建动作中正在做:
params[:event][:start] = Chronic.parse(params[:event][:start])
但是如果验证失败,它会将解析后的值发送回视图,然后我的datetimepicker全部被拙劣。
所以,我想......回调?在我的模型中,我补充道:
private
def date_change
self.start = Chronic.parse(self.start)
end
我尝试了before_save
,before_validation
,after_validation
...但似乎没有任何东西可以正确格式化日期。
目前,我一直在ArgumentError in EventsController#create - Argument out of range
。我认为这是因为数据库期望格式正确的日期时间对象。
关于如何实现我的目标的任何想法,在这里,不更改params
,但仍然能够保存格式正确的对象?
答案 0 :(得分:2)
我猜测问题发生在ActiveRecord提供的start=
mutator方法中。如果你在控制器中做这样的事情:
@event.update_attributes(params[:events])
@event = Event.create(params[:event])
#...
然后create
和update_attributes
应在内部调用start=
。这应该允许您将慢性内容放入您自己的start=
:
def start=(t)
super(Chronic.parse(t))
end
您可能需要针对非字符串t
进行调整,例如,我不确定Chronic.parse(Time.now)
会做什么。如果您不想向write_attribute(:start, Chronic.parse(t))
投标,也可以致电self[:start] = Chronic.parse(t)
或super
。
请注意before_validation
和类似的处理程序将被调用太晚,无法绕过ActiveRecord正在执行的默认字符串到时间戳的转换,但是mutator覆盖应该在正确的时间发生。
或者,您可以使用以下内容解析控制器中的时间:
event = params[:events].dup
events[:start] = Chronic.parse(events[:start])
@event = Event.create(event)
答案 1 :(得分:0)
假设是所有陷入困境的母亲:)
Argument out of range
错误。大多数情况下很难找到/修复错误,因为我们假设我们知道错误,但我们正在以错误的方式查看错误。
测试哪个属性导致错误的简便方法:
打开rails console
,使用参数构建对象,保存并询问错误。像
e = Event.new(params [:event])#copy params from loglog from logfile e.save e.errors
,这将显示哪个字段导致错误。
或者:使用pry并在保存后添加一行binding.pry
,以便检查errors
(更多info)
我看到两个选项可以做你想做的事情:
after_validation
回调,如果您确定数据始终正确,并由Chronic
正确解析。这样,如果验证通过,则转换字段,通常不会出现任何问题,并且该值永远不会再次发送到浏览器。 注意:如果某个其他属性导致错误,那么此回调永远不会被命中。因为它没有通过验证。
start_str
,它是你开始的视觉表现,和
before_save
将其转换为start
。这里真的不重要,因为如果验证失败,您只需显示start_str
而不是“真正的”start
字段。