defra_ruby_address 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +16 -0
- data/lib/defra_ruby/address/helmert_transformation.rb +102 -0
- data/lib/defra_ruby/address/services/base_service.rb +2 -2
- data/lib/defra_ruby/address/services/easting_northing_to_lat_lon_service.rb +18 -0
- data/lib/defra_ruby/address/services/lat_lon_to_easting_northing_service.rb +20 -0
- data/lib/defra_ruby/address/transverse_mercator_projection.rb +151 -0
- data/lib/defra_ruby/address/version.rb +1 -1
- data/lib/defra_ruby/address.rb +4 -0
- metadata +6 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a5d4b459711e84d2d0caac1f48600cb928c1cede9b4ca85e5d23e53b12f4a881
|
|
4
|
+
data.tar.gz: 0c6b7e465734d6f4cc4cbea1df20b40a2d93d9e0d38035dc7d2d8ffbe639855e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c80f7606cbfffc7dc4f03c06b106c2df3d23ad5c4fd93e29849c3ff035e6b5d53836b8bad16816f40164674de1d9437b07792d13410d99b8df4775cb72c10c2c
|
|
7
|
+
data.tar.gz: 7dc7df096183d0422971325ba71e4f5607b9e279833f10d8bd86249ef808af6c758be28a610e16bfb6f2604489992fbfa3eba0c089543fabbe2d6bec9197029b
|
data/README.md
CHANGED
|
@@ -270,6 +270,22 @@ The expected format of each result matches the EA Address Facade v1.1 format:
|
|
|
270
270
|
}
|
|
271
271
|
```
|
|
272
272
|
|
|
273
|
+
### Coordinate conversion
|
|
274
|
+
|
|
275
|
+
The gem also provides a pair of services for converting British National Grid easting and northing coordinates (OSGB36) to WGS84 latitude and longitude, and back again, for example to support geospatial queries.
|
|
276
|
+
|
|
277
|
+
The conversion is pure Ruby, using the 7-parameter Helmert transformation and Transverse Mercator formulae from the OS guide [A guide to coordinate systems in Great Britain](https://www.ordnancesurvey.co.uk/documents/resources/guide-coordinate-systems-great-britain.pdf), and is accurate to around 5 metres.
|
|
278
|
+
|
|
279
|
+
Unlike the address lookup services these do not call an external API, and they return a plain hash rather than a `Response` object. String arguments are coerced to floats.
|
|
280
|
+
|
|
281
|
+
```ruby
|
|
282
|
+
DefraRuby::Address::EastingNorthingToLatLonService.run(358_130, 172_688)
|
|
283
|
+
# => { latitude: 51.45161..., longitude: -2.60394... }
|
|
284
|
+
|
|
285
|
+
DefraRuby::Address::LatLonToEastingNorthingService.run(51.451616, -2.603943)
|
|
286
|
+
# => { easting: 358129.8..., northing: 172687.8... }
|
|
287
|
+
```
|
|
288
|
+
|
|
273
289
|
## Contributing to this project
|
|
274
290
|
|
|
275
291
|
If you have an idea you'd like to contribute please log an issue.
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module DefraRuby
|
|
4
|
+
module Address
|
|
5
|
+
# Shifts latitude/longitude between the OSGB36 and WGS84 datums using the
|
|
6
|
+
# 7-parameter Helmert transformation from the OS guide "A guide to
|
|
7
|
+
# coordinate systems in Great Britain". Accurate to around 5 metres.
|
|
8
|
+
#
|
|
9
|
+
# The OSGB36 to WGS84 direction is ported from the breasal gem
|
|
10
|
+
# (https://github.com/theodi/breasal, MIT licence, copyright 2013
|
|
11
|
+
# pezholio), corrected to the published OS guide parameters. The reverse
|
|
12
|
+
# direction just negates them.
|
|
13
|
+
class HelmertTransformation
|
|
14
|
+
AIRY_1830 = { a: 6_377_563.396, b: 6_356_256.909 }.freeze
|
|
15
|
+
WGS84 = { a: 6_378_137.0, b: 6_356_752.3141 }.freeze
|
|
16
|
+
|
|
17
|
+
ARC_SECOND_IN_RADIANS = Math::PI / 648_000
|
|
18
|
+
|
|
19
|
+
# Translations (tx, ty, tz) in metres, scale change (s) in parts per
|
|
20
|
+
# unit and rotations (rx, ry, rz) in radians, for the OSGB36 to WGS84
|
|
21
|
+
# direction; negated they transform in the opposite direction.
|
|
22
|
+
PARAMETERS = {
|
|
23
|
+
tx: 446.448,
|
|
24
|
+
ty: -125.157,
|
|
25
|
+
tz: 542.060,
|
|
26
|
+
s: -0.0000204894,
|
|
27
|
+
rx: 0.1502 * ARC_SECOND_IN_RADIANS,
|
|
28
|
+
ry: 0.2470 * ARC_SECOND_IN_RADIANS,
|
|
29
|
+
rz: 0.8421 * ARC_SECOND_IN_RADIANS
|
|
30
|
+
}.freeze
|
|
31
|
+
|
|
32
|
+
def self.osgb36_to_wgs84(latitude, longitude)
|
|
33
|
+
new(AIRY_1830, WGS84, 1).transform(latitude, longitude)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.wgs84_to_osgb36(latitude, longitude)
|
|
37
|
+
new(WGS84, AIRY_1830, -1).transform(latitude, longitude)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def initialize(source_ellipsoid, target_ellipsoid, direction)
|
|
41
|
+
@source_ellipsoid = source_ellipsoid
|
|
42
|
+
@target_ellipsoid = target_ellipsoid
|
|
43
|
+
@direction = direction
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def transform(latitude, longitude)
|
|
47
|
+
to_geodetic(apply_helmert(to_cartesian(latitude, longitude)))
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
attr_reader :source_ellipsoid, :target_ellipsoid, :direction
|
|
53
|
+
|
|
54
|
+
def to_cartesian(latitude, longitude)
|
|
55
|
+
e_squared = eccentricity_squared(source_ellipsoid)
|
|
56
|
+
phi = latitude * Math::PI / 180
|
|
57
|
+
lambda = longitude * Math::PI / 180
|
|
58
|
+
nu = source_ellipsoid[:a] / Math.sqrt(1.0 - (e_squared * (Math.sin(phi)**2)))
|
|
59
|
+
|
|
60
|
+
[nu * Math.cos(phi) * Math.cos(lambda),
|
|
61
|
+
nu * Math.cos(phi) * Math.sin(lambda),
|
|
62
|
+
(1.0 - e_squared) * nu * Math.sin(phi)]
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def apply_helmert(cartesian)
|
|
66
|
+
x, y, z = cartesian
|
|
67
|
+
scale = 1.0 + parameter(:s)
|
|
68
|
+
rx = parameter(:rx)
|
|
69
|
+
ry = parameter(:ry)
|
|
70
|
+
rz = parameter(:rz)
|
|
71
|
+
|
|
72
|
+
[parameter(:tx) + (scale * x) - (rz * y) + (ry * z),
|
|
73
|
+
parameter(:ty) + (rz * x) + (scale * y) - (rx * z),
|
|
74
|
+
parameter(:tz) - (ry * x) + (rx * y) + (scale * z)]
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def to_geodetic(cartesian)
|
|
78
|
+
x, y, z = cartesian
|
|
79
|
+
e_squared = eccentricity_squared(target_ellipsoid)
|
|
80
|
+
p = Math.hypot(x, y)
|
|
81
|
+
phi = Math.atan(z / (p * (1.0 - e_squared)))
|
|
82
|
+
|
|
83
|
+
10.times do
|
|
84
|
+
nu = target_ellipsoid[:a] / Math.sqrt(1.0 - (e_squared * (Math.sin(phi)**2)))
|
|
85
|
+
phi = Math.atan((z + (e_squared * nu * Math.sin(phi))) / p)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
[phi * 180 / Math::PI, Math.atan2(y, x) * 180 / Math::PI]
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def parameter(key)
|
|
92
|
+
direction * PARAMETERS[key]
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def eccentricity_squared(ellipsoid)
|
|
96
|
+
a = ellipsoid[:a]
|
|
97
|
+
b = ellipsoid[:b]
|
|
98
|
+
((a * a) - (b * b)) / (a * a)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module DefraRuby
|
|
4
|
+
module Address
|
|
5
|
+
# Converts a British National Grid easting and northing to a WGS84
|
|
6
|
+
# latitude and longitude. Accurate to around 5 metres.
|
|
7
|
+
class EastingNorthingToLatLonService < BaseService
|
|
8
|
+
def run(easting, northing)
|
|
9
|
+
osgb36_latitude, osgb36_longitude = TransverseMercatorProjection.easting_northing_to_lat_lon(
|
|
10
|
+
Float(easting), Float(northing)
|
|
11
|
+
)
|
|
12
|
+
latitude, longitude = HelmertTransformation.osgb36_to_wgs84(osgb36_latitude, osgb36_longitude)
|
|
13
|
+
|
|
14
|
+
{ latitude: latitude, longitude: longitude }
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module DefraRuby
|
|
4
|
+
module Address
|
|
5
|
+
# Converts a WGS84 latitude and longitude to a British National Grid
|
|
6
|
+
# easting and northing. Accurate to around 5 metres.
|
|
7
|
+
class LatLonToEastingNorthingService < BaseService
|
|
8
|
+
def run(latitude, longitude)
|
|
9
|
+
osgb36_latitude, osgb36_longitude = HelmertTransformation.wgs84_to_osgb36(
|
|
10
|
+
Float(latitude), Float(longitude)
|
|
11
|
+
)
|
|
12
|
+
easting, northing = TransverseMercatorProjection.lat_lon_to_easting_northing(
|
|
13
|
+
osgb36_latitude, osgb36_longitude
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
{ easting: easting, northing: northing }
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module DefraRuby
|
|
4
|
+
module Address
|
|
5
|
+
# Converts between British National Grid easting/northing and OSGB36
|
|
6
|
+
# latitude/longitude, a Transverse Mercator projection on the Airy 1830
|
|
7
|
+
# ellipsoid. Variable names follow the terms in the OS guide "A guide to
|
|
8
|
+
# coordinate systems in Great Britain".
|
|
9
|
+
#
|
|
10
|
+
# The easting/northing to lat/lon direction is ported from the breasal
|
|
11
|
+
# gem (https://github.com/theodi/breasal, MIT licence, copyright 2013
|
|
12
|
+
# pezholio). Breasal has no reverse conversion, so that direction comes
|
|
13
|
+
# straight from the OS guide's forward projection formulae.
|
|
14
|
+
class TransverseMercatorProjection
|
|
15
|
+
A = HelmertTransformation::AIRY_1830[:a]
|
|
16
|
+
B = HelmertTransformation::AIRY_1830[:b]
|
|
17
|
+
E_SQUARED = ((A * A) - (B * B)) / (A * A)
|
|
18
|
+
N = (A - B) / (A + B)
|
|
19
|
+
|
|
20
|
+
F0 = 0.9996012717
|
|
21
|
+
PHI0 = 49.0 * Math::PI / 180
|
|
22
|
+
LAMBDA0 = -2.0 * Math::PI / 180
|
|
23
|
+
E0 = 400_000.0
|
|
24
|
+
N0 = -100_000.0
|
|
25
|
+
|
|
26
|
+
def self.easting_northing_to_lat_lon(easting, northing)
|
|
27
|
+
new.easting_northing_to_lat_lon(easting, northing)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def self.lat_lon_to_easting_northing(latitude, longitude)
|
|
31
|
+
new.lat_lon_to_easting_northing(latitude, longitude)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def easting_northing_to_lat_lon(easting, northing)
|
|
35
|
+
phi_prime = converged_phi_prime(northing)
|
|
36
|
+
delta_e = easting - E0
|
|
37
|
+
|
|
38
|
+
[latitude_from(phi_prime, delta_e) * 180 / Math::PI,
|
|
39
|
+
longitude_from(phi_prime, delta_e) * 180 / Math::PI]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def lat_lon_to_easting_northing(latitude, longitude)
|
|
43
|
+
phi = latitude * Math::PI / 180
|
|
44
|
+
delta_lambda = (longitude * Math::PI / 180) - LAMBDA0
|
|
45
|
+
|
|
46
|
+
[easting_from(phi, delta_lambda), northing_from(phi, delta_lambda)]
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
private
|
|
50
|
+
|
|
51
|
+
# Converges within a few iterations for any real coordinates; the cap
|
|
52
|
+
# guards against non-finite input looping forever
|
|
53
|
+
def converged_phi_prime(northing)
|
|
54
|
+
phi_prime = ((northing - N0) / (A * F0)) + PHI0
|
|
55
|
+
|
|
56
|
+
100.times do
|
|
57
|
+
delta = northing - N0 - meridional_arc(phi_prime)
|
|
58
|
+
break if delta < 0.001
|
|
59
|
+
|
|
60
|
+
phi_prime += delta / (A * F0)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
phi_prime
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# The methods below are a straight port of the OS guide formulae; the
|
|
67
|
+
# ABC metric counts every arithmetic operator, so is disabled for them.
|
|
68
|
+
# rubocop:disable Metrics/AbcSize
|
|
69
|
+
|
|
70
|
+
# M in the OS guide
|
|
71
|
+
def meridional_arc(phi)
|
|
72
|
+
delta_phi = phi - PHI0
|
|
73
|
+
sum_phi = phi + PHI0
|
|
74
|
+
|
|
75
|
+
B * F0 * (((1 + N + ((5.0 / 4) * (N**2)) + ((5.0 / 4) * (N**3))) * delta_phi) -
|
|
76
|
+
(((3 * N) + (3 * (N**2)) + ((21.0 / 8) * (N**3))) * Math.sin(delta_phi) * Math.cos(sum_phi)) +
|
|
77
|
+
((((15.0 / 8) * (N**2)) + ((15.0 / 8) * (N**3))) * Math.sin(2 * delta_phi) * Math.cos(2 * sum_phi)) -
|
|
78
|
+
(((35.0 / 24) * (N**3)) * Math.sin(3 * delta_phi) * Math.cos(3 * sum_phi)))
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Terms VII, VIII and IX in the OS guide
|
|
82
|
+
def latitude_from(phi_prime, delta_e)
|
|
83
|
+
tan = Math.tan(phi_prime)
|
|
84
|
+
tan2 = tan**2
|
|
85
|
+
nu = nu(phi_prime)
|
|
86
|
+
rho = rho(phi_prime)
|
|
87
|
+
eta_squared = (nu / rho) - 1.0
|
|
88
|
+
|
|
89
|
+
vii = tan / (2 * rho * nu)
|
|
90
|
+
viii = (tan / (24 * rho * (nu**3))) * (5 + (3 * tan2) + eta_squared - (9 * tan2 * eta_squared))
|
|
91
|
+
ix = (tan / (720 * rho * (nu**5))) * (61 + (90 * tan2) + (45 * (tan2**2)))
|
|
92
|
+
|
|
93
|
+
phi_prime - (vii * (delta_e**2)) + (viii * (delta_e**4)) - (ix * (delta_e**6))
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Terms X, XI, XII and XIIA in the OS guide
|
|
97
|
+
def longitude_from(phi_prime, delta_e)
|
|
98
|
+
sec = 1.0 / Math.cos(phi_prime)
|
|
99
|
+
tan2 = Math.tan(phi_prime)**2
|
|
100
|
+
nu = nu(phi_prime)
|
|
101
|
+
|
|
102
|
+
x = sec / nu
|
|
103
|
+
xi = (sec / (6 * (nu**3))) * ((nu / rho(phi_prime)) + (2 * tan2))
|
|
104
|
+
xii = (sec / (120 * (nu**5))) * (5 + (28 * tan2) + (24 * (tan2**2)))
|
|
105
|
+
xiia = (sec / (5040 * (nu**7))) * (61 + (662 * tan2) + (1320 * (tan2**2)) + (720 * (tan2**3)))
|
|
106
|
+
|
|
107
|
+
LAMBDA0 + (x * delta_e) - (xi * (delta_e**3)) + (xii * (delta_e**5)) - (xiia * (delta_e**7))
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Terms IV, V and VI in the OS guide
|
|
111
|
+
def easting_from(phi, delta_lambda)
|
|
112
|
+
nu = nu(phi)
|
|
113
|
+
rho = rho(phi)
|
|
114
|
+
eta_squared = (nu / rho) - 1.0
|
|
115
|
+
cos_phi = Math.cos(phi)
|
|
116
|
+
tan2 = Math.tan(phi)**2
|
|
117
|
+
|
|
118
|
+
iv = nu * cos_phi
|
|
119
|
+
v = (nu / 6) * (cos_phi**3) * ((nu / rho) - tan2)
|
|
120
|
+
vi = (nu / 120) * (cos_phi**5) * (5 - (18 * tan2) + (tan2**2) + (14 * eta_squared) - (58 * tan2 * eta_squared))
|
|
121
|
+
|
|
122
|
+
E0 + (iv * delta_lambda) + (v * (delta_lambda**3)) + (vi * (delta_lambda**5))
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Terms I, II, III and IIIA in the OS guide
|
|
126
|
+
def northing_from(phi, delta_lambda)
|
|
127
|
+
nu = nu(phi)
|
|
128
|
+
eta_squared = (nu / rho(phi)) - 1.0
|
|
129
|
+
sin_phi = Math.sin(phi)
|
|
130
|
+
cos_phi = Math.cos(phi)
|
|
131
|
+
tan2 = Math.tan(phi)**2
|
|
132
|
+
|
|
133
|
+
i = meridional_arc(phi) + N0
|
|
134
|
+
ii = (nu / 2) * sin_phi * cos_phi
|
|
135
|
+
iii = (nu / 24) * sin_phi * (cos_phi**3) * (5 - tan2 + (9 * eta_squared))
|
|
136
|
+
iiia = (nu / 720) * sin_phi * (cos_phi**5) * (61 - (58 * tan2) + (tan2**2))
|
|
137
|
+
|
|
138
|
+
i + (ii * (delta_lambda**2)) + (iii * (delta_lambda**4)) + (iiia * (delta_lambda**6))
|
|
139
|
+
end
|
|
140
|
+
# rubocop:enable Metrics/AbcSize
|
|
141
|
+
|
|
142
|
+
def nu(phi)
|
|
143
|
+
A * F0 * ((1.0 - (E_SQUARED * (Math.sin(phi)**2)))**-0.5)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def rho(phi)
|
|
147
|
+
A * F0 * (1.0 - E_SQUARED) * ((1.0 - (E_SQUARED * (Math.sin(phi)**2)))**-1.5)
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
data/lib/defra_ruby/address.rb
CHANGED
|
@@ -2,12 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative "address/configuration"
|
|
4
4
|
require_relative "address/ea_address_facade_request"
|
|
5
|
+
require_relative "address/helmert_transformation"
|
|
5
6
|
require_relative "address/no_match_error"
|
|
6
7
|
require_relative "address/response"
|
|
8
|
+
require_relative "address/transverse_mercator_projection"
|
|
7
9
|
|
|
8
10
|
require_relative "address/services/base_service"
|
|
9
11
|
require_relative "address/services/ea_address_facade_v1_1_service"
|
|
10
12
|
require_relative "address/services/ea_address_facade_v1_service"
|
|
13
|
+
require_relative "address/services/easting_northing_to_lat_lon_service"
|
|
14
|
+
require_relative "address/services/lat_lon_to_easting_northing_service"
|
|
11
15
|
require_relative "address/services/os_api_address_lookup_v1_service"
|
|
12
16
|
require_relative "address/services/os_places_address_lookup_service"
|
|
13
17
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: defra_ruby_address
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Defra
|
|
@@ -40,13 +40,17 @@ files:
|
|
|
40
40
|
- lib/defra_ruby/address.rb
|
|
41
41
|
- lib/defra_ruby/address/configuration.rb
|
|
42
42
|
- lib/defra_ruby/address/ea_address_facade_request.rb
|
|
43
|
+
- lib/defra_ruby/address/helmert_transformation.rb
|
|
43
44
|
- lib/defra_ruby/address/no_match_error.rb
|
|
44
45
|
- lib/defra_ruby/address/response.rb
|
|
45
46
|
- lib/defra_ruby/address/services/base_service.rb
|
|
46
47
|
- lib/defra_ruby/address/services/ea_address_facade_v1_1_service.rb
|
|
47
48
|
- lib/defra_ruby/address/services/ea_address_facade_v1_service.rb
|
|
49
|
+
- lib/defra_ruby/address/services/easting_northing_to_lat_lon_service.rb
|
|
50
|
+
- lib/defra_ruby/address/services/lat_lon_to_easting_northing_service.rb
|
|
48
51
|
- lib/defra_ruby/address/services/os_api_address_lookup_v1_service.rb
|
|
49
52
|
- lib/defra_ruby/address/services/os_places_address_lookup_service.rb
|
|
53
|
+
- lib/defra_ruby/address/transverse_mercator_projection.rb
|
|
50
54
|
- lib/defra_ruby/address/version.rb
|
|
51
55
|
homepage: https://github.com/DEFRA/defra-ruby-address
|
|
52
56
|
licenses:
|
|
@@ -61,7 +65,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
61
65
|
requirements:
|
|
62
66
|
- - ">="
|
|
63
67
|
- !ruby/object:Gem::Version
|
|
64
|
-
version: '
|
|
68
|
+
version: '3.2'
|
|
65
69
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
66
70
|
requirements:
|
|
67
71
|
- - ">="
|