Module: HasDuration::ActiveRecordExtension

Defined in:
lib/has_duration.rb

Instance Method Summary collapse

Instance Method Details

#has_duration(field_name) ⇒ Object

Adds a field to your ActiveRecord model that validates and serializes ActiveSupport::Duration objects, like: ‘1 year’, ‘2 seconds’, etc.

For example:

class VisitDuration < ActiveRecord::Base
  has_duration :doctor
  validates :doctor, presence: true
  has_duration :club
end

# ruby > durations = VisitDuration.create(doctor: 1.hour, club: 4.hours)
# ruby > Time.now
# => 2012-09-16 12:12:22 -0300 
# ruby > durations.doctor.from_now
# => 2012-09-16 13:12:22 -0300


50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/has_duration.rb', line 50

def has_duration(field_name)
  serialize field_name, DurationSerializer
  validates field_name, duration: true

  define_method("#{field_name}_unit") do
    return instance_eval("@#{field_name}_unit") if instance_eval("@#{field_name}_unit")
    send(field_name).inspect.split(' ').last.singularize if send(field_name).is_a?(ActiveSupport::Duration)
  end

  define_method("#{field_name}_unit=") do |unit|
    return unless unit =~ /^(year|month|week|day|hour|minute|second)s?$/
    instance_eval "@#{field_name}_unit = '#{unit}'"
    if size = instance_eval("@#{field_name}_size")
      self.send("#{field_name}=", size.to_i.send(unit))
    end
  end

  define_method("#{field_name}_size") do
    return instance_eval("@#{field_name}_size") if instance_eval("@#{field_name}_size")
    send(field_name).inspect.split(' ').first if send(field_name).is_a?(ActiveSupport::Duration)
  end

  define_method("#{field_name}_size=") do |size|
    return unless size.to_s =~ /^(\d{0,10})$/
    instance_eval "@#{field_name}_size = '#{size}'"
    if unit = instance_eval("@#{field_name}_unit")
      self.send("#{field_name}=", size.to_i.send(unit))
    end
  end
end