1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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
80
81
82
83
84
85
86
87
88
89
90
91
|
module ActiveRecord
module ConnectionAdapters
module PostgreSQL
module OID # :nodoc:
class Range < Type::Value # :nodoc:
attr_reader :subtype, :type
delegate :user_input_in_time_zone, to: :subtype
def initialize(subtype, type = :range)
@subtype = subtype
@type = type
end
def type_cast_for_schema(value)
value.inspect.gsub("Infinity", "::Float::INFINITY")
end
def cast_value(value)
return if value == "empty"
return value unless value.is_a?(::String)
extracted = extract_bounds(value)
from = type_cast_single extracted[:from]
to = type_cast_single extracted[:to]
if !infinity?(from) && extracted[:exclude_start]
raise ArgumentError, "The Ruby Range object does not support excluding the beginning of a Range. (unsupported value: '#{value}')"
end
::Range.new(from, to, extracted[:exclude_end])
end
def serialize(value)
if value.is_a?(::Range)
from = type_cast_single_for_database(value.begin)
to = type_cast_single_for_database(value.end)
"[#{from},#{to}#{value.exclude_end? ? ')' : ']'}"
else
super
end
end
def ==(other)
other.is_a?(Range) &&
other.subtype == subtype &&
other.type == type
end
def map(value) # :nodoc:
new_begin = yield(value.begin)
new_end = yield(value.end)
::Range.new(new_begin, new_end, value.exclude_end?)
end
private
def type_cast_single(value)
infinity?(value) ? value : @subtype.deserialize(value)
end
def type_cast_single_for_database(value)
infinity?(value) ? "" : @subtype.serialize(value)
end
def extract_bounds(value)
from, to = value[1..-2].split(",")
{
from: (value[1] == "," || from == "-infinity") ? infinity(negative: true) : from,
to: (value[-2] == "," || to == "infinity") ? infinity : to,
exclude_start: (value[0] == "("),
exclude_end: (value[-1] == ")")
}
end
def infinity(negative: false)
if subtype.respond_to?(:infinity)
subtype.infinity(negative: negative)
elsif negative
-::Float::INFINITY
else
::Float::INFINITY
end
end
def infinity?(value)
value.respond_to?(:infinite?) && value.infinite?
end
end
end
end
end
end
|