我有一个Attendance
模型,允许用户输入开始,结束和休息时间,每个模型都作为ruby Time
对象。每次出席都有一个day
(ruby Date
对象)。我希望时间的'Date'元素相同,所以我覆盖了这样的赋值运算符:
def startTime= (t)
self[:startTime] = Time.mktime(day.year, day.month, day.day, t.hour, t.min)
end
def endTime= (t)
self[:endTime] = Time.mktime(day.year, day.month, day.day, t.hour, t.min)
end
def breakTime= (t)
self[:breakTime] = Time.mktime(day.year, day.month, day.day, t.hour, t.min)
end
我的问题是,当我覆盖breakTime=
函数时,我的测试仅 。他们都拨打new
,即att = Attendance.new @valid_attributes
,特别是breakTime=
来电时失败:
未定义的方法`年'为nil:NilClass
显然,breakTime=
在对象上定义day
之前被调用,即使startTime=
和endTime=
没有被调用到这么早。我意识到这个覆盖可能不够优雅,但我对rails很新,所以我想有人之前犯了这个错误。我该怎么做这个不同的方式?
答案 0 :(得分:4)
不是覆盖属性设置器,而是在保存模型之前使用before_save
回调来更改属性:
class Attendance < ActiveRecord::Base
before_save :update_timestamps
protected
def update_timestamps
self.start_time = Time.mktime(day.year, day.month, day.day, start_time.hour, start_time.min)
# And similarly for the other columns
end
end
有关回调如何工作的概述,请参阅guides.rubyonrails.org上的Active Record Validations and Callbacks guide。
答案 1 :(得分:1)
为什么不使用活动记录回调。 before_save可以帮助你。
答案 2 :(得分:1)
如果您希望坚持使用覆盖方法(其优点是即使未保存的模型也符合常见的时间格式化属性),您需要在每个方法中调用超类的实现:
def startTime= (t)
t = Time.mktime(day.year, day.month, day.day, t.hour, t.min)
super t
end
def endTime= (t)
t = Time.mktime(day.year, day.month, day.day, t.hour, t.min)
super t
end
def breakTime= (t)
t = Time.mktime(day.year, day.month, day.day, t.hour, t.min)
super t
end