如何在保存之前引用属性?

时间:2010-11-17 02:11:18

标签: ruby-on-rails ruby activerecord attributes virtual

我有一个预约模型,其约会属性为date,并且具有虚拟属性duration,表示约会需要多长时间。真实属性booking_end需要在我的应用程序中引用的Time。但是,为了便于输入,我们使用持续时间而不是选择另一个Time。字段如下:

def duration
  ( (booking_end - date) / 1.hour ).round( 2 ) rescue nil
end

def duration=(temp)
  if ( true if Float(temp) rescue false )
    self.booking_end = time_round(date + temp.to_f.hours, 15.minutes)
  else  
    errors.add(:duration, "must be a number, stated in hours.")
    self.booking_end = nil
  end
end

当我在创建新记录时引用date字段时,整个事情都失败了。我收到'nil'错误,因为date尚未初始化。我该如何解决这个问题?其余部分在更新现有记录时有效。

2 个答案:

答案 0 :(得分:0)

当您致电 Reservation.new(:date => date,:duration => duration) ActiveRecord :: Base以这种方式分配属性值(请参阅assign_attributes方法):

attributes.each do |k, v|
  ...
  respond_to?("#{k}=") ? send("#{k}="", v) 
  ...

哈希#每个方法在:date 之前访问:duration 键的方式遍历值,因此 date duration = 方法中为零:

ruby-1.8.7-p302 > {:date => Date.today, :duration => 5}.each do |key,value|
ruby-1.8.7-p302 >     puts "#{key} = #{value}"
ruby-1.8.7-p302 ?>  end
duration = 5
date = 2010-11-17

因此,您必须在初始化后调用 duration =

或者您可以重新定义Reservation#initialize以使用:date调用super,然后使用其余参数调用update_attributes。

答案 1 :(得分:0)

我尝试用

初始化模型
Reservation.new(params[:reservation][:date]) 

然后在其上调用update_attributes。这适用于控制台,但不是。似乎唯一可行的解​​决方法是从params哈希中剥离持续时间,然后在保存之前将其传回。这看起来真的很愚蠢,而且可能不是正确或Rails做事的方式。使用4行,其中一行就足够了。

duration = params[:reservation][:duration]
params[:reservation].delete('duration')
@reservation = Reservation.new(params[:reservation])
@reservation.duration = duration
# Then go to save, etc.

是否有不同的方法来初始化模型或者可能从模型内部访问属性哈希?