从哈希构造时,ruby-on-rails的操作顺序是什么?

时间:2010-07-08 10:38:49

标签: ruby-on-rails ruby

我有一个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很新,所以我想有人之前犯了这个错误。我该怎么做这个不同的方式?

3 个答案:

答案 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