maxmind-geoip2 0.0.1 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +30 -0
- data/Gemfile +1 -5
- data/README.md +121 -0
- data/lib/maxmind/geoip2.rb +1 -13
- data/lib/maxmind/geoip2/client.rb +328 -0
- data/lib/maxmind/geoip2/errors.rb +37 -3
- data/lib/maxmind/geoip2/model/abstract.rb +31 -0
- data/lib/maxmind/geoip2/model/anonymous_ip.rb +75 -0
- data/lib/maxmind/geoip2/model/asn.rb +43 -0
- data/lib/maxmind/geoip2/model/city.rb +63 -44
- data/lib/maxmind/geoip2/model/connection_type.rb +36 -0
- data/lib/maxmind/geoip2/model/country.rb +64 -45
- data/lib/maxmind/geoip2/model/domain.rb +36 -0
- data/lib/maxmind/geoip2/model/enterprise.rb +13 -9
- data/lib/maxmind/geoip2/model/insights.rb +18 -0
- data/lib/maxmind/geoip2/model/isp.rb +57 -0
- data/lib/maxmind/geoip2/reader.rb +250 -131
- data/lib/maxmind/geoip2/record/abstract.rb +17 -12
- data/lib/maxmind/geoip2/record/city.rb +33 -24
- data/lib/maxmind/geoip2/record/continent.rb +32 -23
- data/lib/maxmind/geoip2/record/country.rb +47 -34
- data/lib/maxmind/geoip2/record/location.rb +64 -50
- data/lib/maxmind/geoip2/record/maxmind.rb +21 -0
- data/lib/maxmind/geoip2/record/place.rb +22 -16
- data/lib/maxmind/geoip2/record/postal.rb +26 -18
- data/lib/maxmind/geoip2/record/represented_country.rb +20 -14
- data/lib/maxmind/geoip2/record/subdivision.rb +42 -34
- data/lib/maxmind/geoip2/record/traits.rb +204 -160
- data/maxmind-geoip2.gemspec +12 -2
- data/test/data/LICENSE +4 -0
- data/test/data/MaxMind-DB-spec.md +570 -0
- data/test/data/MaxMind-DB-test-metadata-pointers.mmdb +0 -0
- data/test/data/README.md +4 -0
- data/test/data/bad-data/README.md +7 -0
- data/test/data/bad-data/libmaxminddb/libmaxminddb-offset-integer-overflow.mmdb +0 -0
- data/test/data/bad-data/maxminddb-golang/cyclic-data-structure.mmdb +0 -0
- data/test/data/bad-data/maxminddb-golang/invalid-bytes-length.mmdb +1 -0
- data/test/data/bad-data/maxminddb-golang/invalid-data-record-offset.mmdb +0 -0
- data/test/data/bad-data/maxminddb-golang/invalid-map-key-length.mmdb +0 -0
- data/test/data/bad-data/maxminddb-golang/invalid-string-length.mmdb +1 -0
- data/test/data/bad-data/maxminddb-golang/metadata-is-an-uint128.mmdb +1 -0
- data/test/data/bad-data/maxminddb-golang/unexpected-bytes.mmdb +0 -0
- data/test/data/bad-data/maxminddb-python/bad-unicode-in-map-key.mmdb +0 -0
- data/test/data/perltidyrc +12 -0
- data/test/data/source-data/GeoIP2-Anonymous-IP-Test.json +49 -0
- data/test/data/source-data/GeoIP2-City-Test.json +12852 -0
- data/test/data/source-data/GeoIP2-Connection-Type-Test.json +102 -0
- data/test/data/source-data/GeoIP2-Country-Test.json +15916 -0
- data/test/data/source-data/GeoIP2-DensityIncome-Test.json +14 -0
- data/test/data/source-data/GeoIP2-Domain-Test.json +452 -0
- data/test/data/source-data/GeoIP2-Enterprise-Test.json +687 -0
- data/test/data/source-data/GeoIP2-ISP-Test.json +12595 -0
- data/test/data/source-data/GeoIP2-Precision-Enterprise-Test.json +2148 -0
- data/test/data/source-data/GeoIP2-Static-IP-Score-Test.json +2132 -0
- data/test/data/source-data/GeoIP2-User-Count-Test.json +2837 -0
- data/test/data/source-data/GeoLite2-ASN-Test.json +37 -0
- data/test/data/source-data/README +15 -0
- data/test/data/test-data/GeoIP2-Anonymous-IP-Test.mmdb +0 -0
- data/test/data/test-data/GeoIP2-City-Test-Broken-Double-Format.mmdb +0 -0
- data/test/data/test-data/GeoIP2-City-Test-Invalid-Node-Count.mmdb +0 -0
- data/test/data/test-data/GeoIP2-City-Test.mmdb +0 -0
- data/test/data/test-data/GeoIP2-Connection-Type-Test.mmdb +0 -0
- data/test/data/test-data/GeoIP2-Country-Test.mmdb +0 -0
- data/test/data/test-data/GeoIP2-DensityIncome-Test.mmdb +0 -0
- data/test/data/test-data/GeoIP2-Domain-Test.mmdb +0 -0
- data/test/data/test-data/GeoIP2-Enterprise-Test.mmdb +0 -0
- data/test/data/test-data/GeoIP2-ISP-Test.mmdb +0 -0
- data/test/data/test-data/GeoIP2-Precision-Enterprise-Test.mmdb +0 -0
- data/test/data/test-data/GeoIP2-Static-IP-Score-Test.mmdb +0 -0
- data/test/data/test-data/GeoIP2-User-Count-Test.mmdb +0 -0
- data/test/data/test-data/GeoLite2-ASN-Test.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-no-ipv4-search-tree.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-string-value-entries.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-broken-pointers-24.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-broken-search-tree-24.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-decoder.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-ipv4-24.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-ipv4-28.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-ipv4-32.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-ipv6-24.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-ipv6-28.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-ipv6-32.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-metadata-pointers.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-mixed-24.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-mixed-28.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-mixed-32.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-nested.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-pointer-decoder.mmdb +0 -0
- data/test/data/test-data/README.md +26 -0
- data/test/data/test-data/maps-with-pointers.raw +0 -0
- data/test/data/test-data/write-test-data.pl +691 -0
- data/test/data/tidyall.ini +5 -0
- data/test/test_client.rb +426 -0
- data/test/test_model_country.rb +1 -1
- data/test/test_model_names.rb +1 -1
- data/test/test_reader.rb +92 -1
- metadata +194 -10
- data/Gemfile.lock +0 -36
@@ -1,7 +1,41 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module MaxMind
|
4
|
-
|
5
|
-
|
3
|
+
module MaxMind
|
4
|
+
module GeoIP2
|
5
|
+
# An AddressNotFoundError means the IP address was not found in the
|
6
|
+
# database or the web service said the IP address was not found.
|
7
|
+
class AddressNotFoundError < RuntimeError
|
8
|
+
end
|
9
|
+
|
10
|
+
# An HTTPError means there was an unexpected HTTP status or response.
|
11
|
+
class HTTPError < RuntimeError
|
12
|
+
end
|
13
|
+
|
14
|
+
# An AddressInvalidError means the IP address was invalid.
|
15
|
+
class AddressInvalidError < RuntimeError
|
16
|
+
end
|
17
|
+
|
18
|
+
# An AddressReservedError means the IP address is reserved.
|
19
|
+
class AddressReservedError < RuntimeError
|
20
|
+
end
|
21
|
+
|
22
|
+
# An AuthenticationError means there was a problem authenticating to the
|
23
|
+
# web service.
|
24
|
+
class AuthenticationError < RuntimeError
|
25
|
+
end
|
26
|
+
|
27
|
+
# An InsufficientFundsError means the account is out of credits.
|
28
|
+
class InsufficientFundsError < RuntimeError
|
29
|
+
end
|
30
|
+
|
31
|
+
# A PermissionRequiredError means the account does not have permission to
|
32
|
+
# use the requested service.
|
33
|
+
class PermissionRequiredError < RuntimeError
|
34
|
+
end
|
35
|
+
|
36
|
+
# An InvalidRequestError means the web service returned an error and there
|
37
|
+
# is no more specific error class.
|
38
|
+
class InvalidRequestError < RuntimeError
|
39
|
+
end
|
6
40
|
end
|
7
41
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'ipaddr'
|
4
|
+
|
5
|
+
module MaxMind
|
6
|
+
module GeoIP2
|
7
|
+
module Model
|
8
|
+
# @!visibility private
|
9
|
+
class Abstract
|
10
|
+
def initialize(record)
|
11
|
+
@record = record
|
12
|
+
|
13
|
+
ip = IPAddr.new(record['ip_address']).mask(record['prefix_length'])
|
14
|
+
record['network'] = format('%s/%d', ip.to_s, record['prefix_length'])
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
def get(key)
|
20
|
+
if @record.nil? || !@record.key?(key)
|
21
|
+
return false if key.start_with?('is_')
|
22
|
+
|
23
|
+
return nil
|
24
|
+
end
|
25
|
+
|
26
|
+
@record[key]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'maxmind/geoip2/model/abstract'
|
4
|
+
|
5
|
+
module MaxMind
|
6
|
+
module GeoIP2
|
7
|
+
module Model
|
8
|
+
# Model class for the Anonymous IP database.
|
9
|
+
class AnonymousIP < Abstract
|
10
|
+
# This is true if the IP address belongs to any sort of anonymous network.
|
11
|
+
#
|
12
|
+
# @return [Boolean]
|
13
|
+
def anonymous?
|
14
|
+
get('is_anonymous')
|
15
|
+
end
|
16
|
+
|
17
|
+
# This is true if the IP address is registered to an anonymous VPN
|
18
|
+
# provider. If a VPN provider does not register subnets under names
|
19
|
+
# associated with them, we will likely only flag their IP ranges using the
|
20
|
+
# hosting_provider? method.
|
21
|
+
#
|
22
|
+
# @return [Boolean]
|
23
|
+
def anonymous_vpn?
|
24
|
+
get('is_anonymous_vpn')
|
25
|
+
end
|
26
|
+
|
27
|
+
# This is true if the IP address belongs to a hosting or VPN provider (see
|
28
|
+
# description of the anonymous_vpn? method).
|
29
|
+
#
|
30
|
+
# @return [Boolean]
|
31
|
+
def hosting_provider?
|
32
|
+
get('is_hosting_provider')
|
33
|
+
end
|
34
|
+
|
35
|
+
# The IP address that the data in the model is for.
|
36
|
+
#
|
37
|
+
# @return [String]
|
38
|
+
def ip_address
|
39
|
+
get('ip_address')
|
40
|
+
end
|
41
|
+
|
42
|
+
# The network in CIDR notation associated with the record. In particular,
|
43
|
+
# this is the largest network where all of the fields besides ip_address
|
44
|
+
# have the same value.
|
45
|
+
#
|
46
|
+
# @return [String]
|
47
|
+
def network
|
48
|
+
get('network')
|
49
|
+
end
|
50
|
+
|
51
|
+
# This is true if the IP address belongs to a public proxy.
|
52
|
+
#
|
53
|
+
# @return [Boolean]
|
54
|
+
def public_proxy?
|
55
|
+
get('is_public_proxy')
|
56
|
+
end
|
57
|
+
|
58
|
+
# This is true if the IP address is on a suspected anonymizing network
|
59
|
+
# and belongs to a residential ISP.
|
60
|
+
#
|
61
|
+
# @return [Boolean]
|
62
|
+
def residential_proxy?
|
63
|
+
get('is_residential_proxy')
|
64
|
+
end
|
65
|
+
|
66
|
+
# This is true if the IP address is a Tor exit node.
|
67
|
+
#
|
68
|
+
# @return [Boolean]
|
69
|
+
def tor_exit_node?
|
70
|
+
get('is_tor_exit_node')
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'maxmind/geoip2/model/abstract'
|
4
|
+
|
5
|
+
module MaxMind
|
6
|
+
module GeoIP2
|
7
|
+
module Model
|
8
|
+
# Model class for the GeoLite2 ASN database.
|
9
|
+
class ASN < Abstract
|
10
|
+
# The autonomous system number associated with the IP address.
|
11
|
+
#
|
12
|
+
# @return [Integer, nil]
|
13
|
+
def autonomous_system_number
|
14
|
+
get('autonomous_system_number')
|
15
|
+
end
|
16
|
+
|
17
|
+
# The organization associated with the registered autonomous system number
|
18
|
+
# for the IP address.
|
19
|
+
#
|
20
|
+
# @return [String, nil]
|
21
|
+
def autonomous_system_organization
|
22
|
+
get('autonomous_system_organization')
|
23
|
+
end
|
24
|
+
|
25
|
+
# The IP address that the data in the model is for.
|
26
|
+
#
|
27
|
+
# @return [String]
|
28
|
+
def ip_address
|
29
|
+
get('ip_address')
|
30
|
+
end
|
31
|
+
|
32
|
+
# The network in CIDR notation associated with the record. In particular,
|
33
|
+
# this is the largest network where all of the fields besides ip_address
|
34
|
+
# have the same value.
|
35
|
+
#
|
36
|
+
# @return [String]
|
37
|
+
def network
|
38
|
+
get('network')
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -6,54 +6,73 @@ require 'maxmind/geoip2/record/location'
|
|
6
6
|
require 'maxmind/geoip2/record/postal'
|
7
7
|
require 'maxmind/geoip2/record/subdivision'
|
8
8
|
|
9
|
-
module MaxMind
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
# Postal data for the IP address. See MaxMind::GeoIP2::Record::Postal.
|
26
|
-
attr_reader :postal
|
27
|
-
|
28
|
-
# An array of MaxMind::GeoIP2::Record::Subdivision objects representing the
|
29
|
-
# country subdivisions for the IP address. The number and type of
|
30
|
-
# subdivisions varies by country, but a subdivision is typically a state,
|
31
|
-
# province, country, etc. Subdivisions are ordered from most general
|
32
|
-
# (largest) to most specific (smallest). If the response did not contain
|
33
|
-
# any subdivisions, this attribute will be an empty array.
|
34
|
-
attr_reader :subdivisions
|
35
|
-
|
36
|
-
def initialize(record, locales) # :nodoc:
|
37
|
-
super(record, locales)
|
38
|
-
@city = MaxMind::GeoIP2::Record::City.new(record['city'], locales)
|
39
|
-
@location = MaxMind::GeoIP2::Record::Location.new(record['location'])
|
40
|
-
@postal = MaxMind::GeoIP2::Record::Postal.new(record['postal'])
|
41
|
-
@subdivisions = create_subdivisions(record['subdivisions'], locales)
|
42
|
-
end
|
9
|
+
module MaxMind
|
10
|
+
module GeoIP2
|
11
|
+
module Model
|
12
|
+
# Model class for the data returned by the GeoIP2 City web service and
|
13
|
+
# database. It is also used for GeoLite2 City lookups.
|
14
|
+
#
|
15
|
+
# The only difference between the City and Insights model classes is which
|
16
|
+
# fields in each record may be populated. See
|
17
|
+
# https://dev.maxmind.com/geoip/geoip2/web-services for more details.
|
18
|
+
#
|
19
|
+
# See {MaxMind::GeoIP2::Model::Country} for inherited methods.
|
20
|
+
class City < Country
|
21
|
+
# City data for the IP address.
|
22
|
+
#
|
23
|
+
# @return [MaxMind::GeoIP2::Record::City]
|
24
|
+
attr_reader :city
|
43
25
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
26
|
+
# Location data for the IP address.
|
27
|
+
#
|
28
|
+
# @return [MaxMind::GeoIP2::Record::Location]
|
29
|
+
attr_reader :location
|
30
|
+
|
31
|
+
# Postal data for the IP address.
|
32
|
+
#
|
33
|
+
# @return [MaxMind::GeoIP2::Record::Postal]
|
34
|
+
attr_reader :postal
|
35
|
+
|
36
|
+
# The country subdivisions for the IP address.
|
37
|
+
#
|
38
|
+
# The number and type of subdivisions varies by country, but a subdivision
|
39
|
+
# is typically a state, province, country, etc. Subdivisions are ordered
|
40
|
+
# from most general (largest) to most specific (smallest).
|
41
|
+
#
|
42
|
+
# If the response did not contain any subdivisions, this attribute will be
|
43
|
+
# an empty array.
|
44
|
+
#
|
45
|
+
# @return [Array<MaxMind::GeoIP2::Record::Subdivision>]
|
46
|
+
attr_reader :subdivisions
|
47
|
+
|
48
|
+
# @!visibility private
|
49
|
+
def initialize(record, locales)
|
50
|
+
super(record, locales)
|
51
|
+
@city = MaxMind::GeoIP2::Record::City.new(record['city'], locales)
|
52
|
+
@location = MaxMind::GeoIP2::Record::Location.new(record['location'])
|
53
|
+
@postal = MaxMind::GeoIP2::Record::Postal.new(record['postal'])
|
54
|
+
@subdivisions = create_subdivisions(record['subdivisions'], locales)
|
55
|
+
end
|
56
|
+
|
57
|
+
# The most specific subdivision returned.
|
58
|
+
#
|
59
|
+
# If the response did not contain any subdivisions, this method returns
|
60
|
+
# nil.
|
61
|
+
#
|
62
|
+
# @return [MaxMind::GeoIP2::Record::Subdivision, nil]
|
63
|
+
def most_specific_subdivision
|
64
|
+
@subdivisions.last
|
65
|
+
end
|
49
66
|
|
50
|
-
|
67
|
+
private
|
51
68
|
|
52
|
-
|
53
|
-
|
69
|
+
def create_subdivisions(subdivisions, locales)
|
70
|
+
return [] if subdivisions.nil?
|
54
71
|
|
55
|
-
|
56
|
-
|
72
|
+
subdivisions.map do |s|
|
73
|
+
MaxMind::GeoIP2::Record::Subdivision.new(s, locales)
|
74
|
+
end
|
75
|
+
end
|
57
76
|
end
|
58
77
|
end
|
59
78
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'maxmind/geoip2/model/abstract'
|
4
|
+
|
5
|
+
module MaxMind
|
6
|
+
module GeoIP2
|
7
|
+
module Model
|
8
|
+
# Model class for the GeoIP2 Connection Type database.
|
9
|
+
class ConnectionType < Abstract
|
10
|
+
# The connection type may take the following values: "Dialup", "Cable/DSL",
|
11
|
+
# "Corporate", "Cellular". Additional values may be added in the future.
|
12
|
+
#
|
13
|
+
# @return [String, nil]
|
14
|
+
def connection_type
|
15
|
+
get('connection_type')
|
16
|
+
end
|
17
|
+
|
18
|
+
# The IP address that the data in the model is for.
|
19
|
+
#
|
20
|
+
# @return [String]
|
21
|
+
def ip_address
|
22
|
+
get('ip_address')
|
23
|
+
end
|
24
|
+
|
25
|
+
# The network in CIDR notation associated with the record. In particular,
|
26
|
+
# this is the largest network where all of the fields besides ip_address
|
27
|
+
# have the same value.
|
28
|
+
#
|
29
|
+
# @return [String]
|
30
|
+
def network
|
31
|
+
get('network')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -2,54 +2,73 @@
|
|
2
2
|
|
3
3
|
require 'maxmind/geoip2/record/continent'
|
4
4
|
require 'maxmind/geoip2/record/country'
|
5
|
+
require 'maxmind/geoip2/record/maxmind'
|
5
6
|
require 'maxmind/geoip2/record/represented_country'
|
6
7
|
require 'maxmind/geoip2/record/traits'
|
7
8
|
|
8
|
-
module MaxMind
|
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
|
-
locales
|
51
|
-
|
52
|
-
|
9
|
+
module MaxMind
|
10
|
+
module GeoIP2
|
11
|
+
module Model
|
12
|
+
# Model class for the data returned by the GeoIP2 Country web service and
|
13
|
+
# database. It is also used for GeoLite2 Country lookups.
|
14
|
+
class Country
|
15
|
+
# Continent data for the IP address.
|
16
|
+
#
|
17
|
+
# @return [MaxMind::GeoIP2::Record::Continent]
|
18
|
+
attr_reader :continent
|
19
|
+
|
20
|
+
# Country data for the IP address. This object represents the country where
|
21
|
+
# MaxMind believes the end user is located.
|
22
|
+
#
|
23
|
+
# @return [MaxMind::GeoIP2::Record::Country]
|
24
|
+
attr_reader :country
|
25
|
+
|
26
|
+
# Data related to your MaxMind account.
|
27
|
+
#
|
28
|
+
# @return [MaxMind::GeoIP2::Record::MaxMind]
|
29
|
+
attr_reader :maxmind
|
30
|
+
|
31
|
+
# Registered country data for the IP address. This record represents the
|
32
|
+
# country where the ISP has registered a given IP block and may differ from
|
33
|
+
# the user's country.
|
34
|
+
#
|
35
|
+
# @return [MaxMind::GeoIP2::Record::Country]
|
36
|
+
attr_reader :registered_country
|
37
|
+
|
38
|
+
# Represented country data for the IP address. The represented country is
|
39
|
+
# used for things like military bases. It is only present when the
|
40
|
+
# represented country differs from the country.
|
41
|
+
#
|
42
|
+
# @return [MaxMind::GeoIP2::Record::RepresentedCountry]
|
43
|
+
attr_reader :represented_country
|
44
|
+
|
45
|
+
# Data for the traits of the IP address.
|
46
|
+
#
|
47
|
+
# @return [MaxMind::GeoIP2::Record::Traits]
|
48
|
+
attr_reader :traits
|
49
|
+
|
50
|
+
# @!visibility private
|
51
|
+
def initialize(record, locales)
|
52
|
+
@continent = MaxMind::GeoIP2::Record::Continent.new(
|
53
|
+
record['continent'],
|
54
|
+
locales,
|
55
|
+
)
|
56
|
+
@country = MaxMind::GeoIP2::Record::Country.new(
|
57
|
+
record['country'],
|
58
|
+
locales,
|
59
|
+
)
|
60
|
+
@maxmind = MaxMind::GeoIP2::Record::MaxMind.new(record['maxmind'])
|
61
|
+
@registered_country = MaxMind::GeoIP2::Record::Country.new(
|
62
|
+
record['registered_country'],
|
63
|
+
locales,
|
64
|
+
)
|
65
|
+
@represented_country = MaxMind::GeoIP2::Record::RepresentedCountry.new(
|
66
|
+
record['represented_country'],
|
67
|
+
locales,
|
68
|
+
)
|
69
|
+
@traits = MaxMind::GeoIP2::Record::Traits.new(record['traits'])
|
70
|
+
end
|
71
|
+
end
|
53
72
|
end
|
54
73
|
end
|
55
74
|
end
|