Class: Torque::PostgreSQL::Adapter::OID::Interval

Inherits:
ActiveModel::Type::Value
  • Object
show all
Defined in:
lib/torque/postgresql/adapter/oid/interval.rb

Constant Summary collapse

CAST_PARTS =
[:years, :months, :days, :hours, :minutes, :seconds]

Instance Method Summary collapse

Instance Method Details

#assert_valid_value(value) ⇒ Object

Check if the user input has the correct format



70
71
72
# File 'lib/torque/postgresql/adapter/oid/interval.rb', line 70

def assert_valid_value(value)
  # TODO: Implement!
end

#cast(value) ⇒ Object

Accepts database-style string, numeric as seconds, array of parts padded to left, or a hash

Examples:

[12, 0, 0]
produces: 12 hours, 0 minutes, and 0 seconds

[nil, nil, 3, 0, 0, 0]
produces: 3 days, 0 hours, 0 minutes, and 0 seconds

{minutes: 12, seconds: 0}
produces: 12 minutes, and 0 seconds


25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/torque/postgresql/adapter/oid/interval.rb', line 25

def cast(value)
  return if value.blank?
  case value
  when ::String then deserialize(value)
  when ::ActiveSupport::Duration then value
  when ::Numeric
    parts = CAST_PARTS.map do |part|
      rest, value = value.divmod(1.send(part))
      rest == 0 ? nil : [part, rest]
    end
    parts_to_duration(parts.compact)
  when ::Array
    value.compact!
    parts = CAST_PARTS.drop(6 - value.size).zip(value).to_h
    parts_to_duration(parts)
  when ::Hash
    parts_to_duration(value)
  else
    value
  end
end

#deserialize(value) ⇒ Object

Uses the ActiveSupport::Duration::ISO8601Parser See ActiveSupport::Duration#parse The value must be Integer when no precision is given



50
51
52
53
# File 'lib/torque/postgresql/adapter/oid/interval.rb', line 50

def deserialize(value)
  return if value.blank?
  ActiveSupport::Duration.parse(value)
end

#parts_to_duration(parts) ⇒ Object

Transform a list of parts into a duration object



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/torque/postgresql/adapter/oid/interval.rb', line 75

def parts_to_duration(parts)
  parts = parts.to_h.slice(*CAST_PARTS)
  return 0.seconds if parts.blank?

  seconds = 0
  parts = parts.map do |part, num|
    num = num.to_i unless num.is_a?(Numeric)
    next if num <= 0

    seconds += num.send(part).value
    [part.to_sym, num]
  end

  ActiveSupport::Duration.new(seconds, parts.compact)
end

#remove_weeks(value) ⇒ Object

As PostgreSQL converts weeks in duration to days, intercept duration values with weeks and turn them into days before serializing so it won’t break because the following issues github.com/crashtech/torque-postgresql/issues/26 github.com/rails/rails/issues/34655



96
97
98
99
100
# File 'lib/torque/postgresql/adapter/oid/interval.rb', line 96

def remove_weeks(value)
  parts = value.parts.dup
  parts[:days] += parts.delete(:weeks) * 7
  ActiveSupport::Duration.new(value.seconds.to_i, parts)
end

#serialize(value) ⇒ Object

Uses the ActiveSupport::Duration::ISO8601Serializer See ActiveSupport::Duration#iso8601



57
58
59
60
61
62
# File 'lib/torque/postgresql/adapter/oid/interval.rb', line 57

def serialize(value)
  return if value.blank?
  value = cast(value) unless value.is_a?(ActiveSupport::Duration)
  value = remove_weeks(value) if value.parts.to_h.key?(:weeks)
  value.iso8601(precision: @scale)
end

#typeObject



9
10
11
# File 'lib/torque/postgresql/adapter/oid/interval.rb', line 9

def type
  :interval
end

#type_cast_for_schema(value) ⇒ Object

Always use the numeric value for schema dumper



65
66
67
# File 'lib/torque/postgresql/adapter/oid/interval.rb', line 65

def type_cast_for_schema(value)
  cast(value).value.inspect
end