/
location.rb
114 lines (94 loc) · 1.96 KB
/
location.rb
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
require 'liquid'
Location = Struct.new(:lat, :lng, :radius, :speed, :course)
class Location
include LiquidDroppable
protected :[]=
def initialize(data = {})
super()
case data
when Array
raise ArgumentError, 'unsupported location data' unless data.size == 2
self.lat, self.lng = data
when Hash, Location
data.each { |key, value|
case key.to_sym
when :lat, :latitude
self.lat = value
when :lng, :longitude
self.lng = value
when :radius
self.radius = value
when :speed
self.speed = value
when :course
self.course = value
end
}
else
raise ArgumentError, 'unsupported location data'
end
yield self if block_given?
end
def lat=(value)
self[:lat] = floatify(value) { |f|
if f.abs <= 90
f
else
raise ArgumentError, 'out of bounds'
end
}
end
alias latitude lat
alias latitude= lat=
def lng=(value)
self[:lng] = floatify(value) { |f|
if f.abs <= 180
f
else
raise ArgumentError, 'out of bounds'
end
}
end
alias longitude lng
alias longitude= lng=
def radius=(value)
self[:radius] = floatify(value) { |f| f if f >= 0 }
end
def speed=(value)
self[:speed] = floatify(value) { |f| f if f >= 0 }
end
def course=(value)
self[:course] = floatify(value) { |f| f if (0..360).cover?(f) }
end
def present?
lat && lng
end
def empty?
!present?
end
def latlng
"#{lat},#{lng}"
end
private
def floatify(value)
case value
when nil, ''
return nil
else
float = Float(value)
if block_given?
yield(float)
else
float
end
end
end
end
class LocationDrop
KEYS = Location.members.map(&:to_s).concat(%w[latitude longitude latlng])
def before_method(key)
if KEYS.include?(key)
@object.__send__(key)
end
end
end