开发者

How can I reference attributes before a save?

I have a Reservation model that takes an appointment attribute as date and has a virtual attribute duration that indicates how long the appointment will take. Th开发者_Python百科e real attribute, booking_end takes a Time that is referenced all over my application. However, for ease of input, we use duration instead of choosing another Time. The fields are below:

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

The whole thing fails when I reference the date field while creating a new record. I get a 'nil' error because date hasn't been initialized. How can I fix this problem? The rest of this works when updating existing records.


When you call Reservation.new(:date => date, :duration => duration) ActiveRecord::Base assigns attributes values this way (see assign_attributes method):

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

Hash#each method iterates through the values the way that :duration key is accessed before :date one, so date is nil inside the duration= method:

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

So you'll have to call duration= after initialization.

Or you can redefine Reservation#initialize to call super with :date and then update_attributes with the rest of parameters.


I tried to initialize the model with

Reservation.new(params[:reservation][:date]) 

and then call update_attributes on it. This works in console, but not otherwise. The only workaround that seems to take hold is stripping duration out of the params hash and then passing it back before save. This seems really stupid, though, and probably not the right or Rails way to do things. Using 4 lines where one should suffice.

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

Is there a different way to initialize the model or perhaps access the attributes hash from inside the model?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜