Reputation: 121
I've got a before_validation
in a model. Its purpose is to calculate the time worked between two DateTime
objects, and insert that value into a time_worked
attribute. Its success depends on the validity of two fields, and it spits out the value of a third field which, in turn, has validations.
class TimeEntry < ActiveRecord::Base
validates :start_time, :end_time, :presence => true
validates :time_worked, :presence => true, :numericality => true
before_validation :calculate_time_worked
def calculate_time_worked
time_float = (Time.parse(self.end_time.to_s) - Time.parse(self.start_time.to_s)) / 1.hour
self.time_worked = ((time_float * 10).ceil).to_f/10
end
The problem is that my calculate_time_worked
method will fail if either start_time
or end_time
are empty or invalid, which is exactly why those two fields have validations!
Any ideas how to refactor?
Upvotes: 0
Views: 149
Reputation: 40277
The before_save solution from @PedroMedeiros will work in this case.... but if you wanted to validate that time_worked is positive, then you would probably do something like this:
validate :calculate_time_worked
def calculate_time_worked
return if end_time.blank? || start_time.blank?
time_float = (Time.parse(self.end_time.to_s) - Time.parse(self.start_time.to_s)) / 1.hour
self.time_worked = ((time_float * 10).ceil).to_f/10
if time_worked < 0
self.errors.add(:end_time, "Must be after Start Time")
end
end
Finally -- this SO question is cool on getting the difference of time in hours
Upvotes: 1
Reputation: 171
it seens that before_validates is called just before those methods are sets. If I where you I would use before_save to calculate_time_worked. once the attrs will set and your validations will be completed.
class TimeEntry < ActiveRecord::Base
validates :start_time, :end_time, :presence => true
validates :time_worked, :presence => true, :numericality => true
before_save :calculate_time_worked
end
Upvotes: 0