maxmind-geoip2 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +7 -0
  3. data/Gemfile.lock +5 -3
  4. data/README.md +69 -0
  5. data/lib/maxmind/geoip2.rb +0 -13
  6. data/lib/maxmind/geoip2/model/abstract.rb +27 -0
  7. data/lib/maxmind/geoip2/model/anonymous_ip.rb +63 -0
  8. data/lib/maxmind/geoip2/model/asn.rb +39 -0
  9. data/lib/maxmind/geoip2/model/city.rb +28 -13
  10. data/lib/maxmind/geoip2/model/connection_type.rb +32 -0
  11. data/lib/maxmind/geoip2/model/country.rb +17 -9
  12. data/lib/maxmind/geoip2/model/domain.rb +32 -0
  13. data/lib/maxmind/geoip2/model/enterprise.rb +1 -1
  14. data/lib/maxmind/geoip2/model/isp.rb +53 -0
  15. data/lib/maxmind/geoip2/reader.rb +176 -59
  16. data/lib/maxmind/geoip2/record/abstract.rb +2 -1
  17. data/lib/maxmind/geoip2/record/city.rb +11 -6
  18. data/lib/maxmind/geoip2/record/continent.rb +11 -6
  19. data/lib/maxmind/geoip2/record/country.rb +17 -8
  20. data/lib/maxmind/geoip2/record/location.rb +18 -8
  21. data/lib/maxmind/geoip2/record/place.rb +5 -3
  22. data/lib/maxmind/geoip2/record/postal.rb +6 -2
  23. data/lib/maxmind/geoip2/record/represented_country.rb +4 -2
  24. data/lib/maxmind/geoip2/record/subdivision.rb +14 -10
  25. data/lib/maxmind/geoip2/record/traits.rb +52 -21
  26. data/maxmind-geoip2.gemspec +3 -1
  27. data/test/data/LICENSE +4 -0
  28. data/test/data/MaxMind-DB-spec.md +570 -0
  29. data/test/data/MaxMind-DB-test-metadata-pointers.mmdb +0 -0
  30. data/test/data/README.md +4 -0
  31. data/test/data/bad-data/README.md +7 -0
  32. data/test/data/bad-data/libmaxminddb/libmaxminddb-offset-integer-overflow.mmdb +0 -0
  33. data/test/data/bad-data/maxminddb-golang/cyclic-data-structure.mmdb +0 -0
  34. data/test/data/bad-data/maxminddb-golang/invalid-bytes-length.mmdb +1 -0
  35. data/test/data/bad-data/maxminddb-golang/invalid-data-record-offset.mmdb +0 -0
  36. data/test/data/bad-data/maxminddb-golang/invalid-map-key-length.mmdb +0 -0
  37. data/test/data/bad-data/maxminddb-golang/invalid-string-length.mmdb +1 -0
  38. data/test/data/bad-data/maxminddb-golang/metadata-is-an-uint128.mmdb +1 -0
  39. data/test/data/bad-data/maxminddb-golang/unexpected-bytes.mmdb +0 -0
  40. data/test/data/perltidyrc +12 -0
  41. data/test/data/source-data/GeoIP2-Anonymous-IP-Test.json +48 -0
  42. data/test/data/source-data/GeoIP2-City-Test.json +12852 -0
  43. data/test/data/source-data/GeoIP2-Connection-Type-Test.json +102 -0
  44. data/test/data/source-data/GeoIP2-Country-Test.json +15916 -0
  45. data/test/data/source-data/GeoIP2-DensityIncome-Test.json +14 -0
  46. data/test/data/source-data/GeoIP2-Domain-Test.json +452 -0
  47. data/test/data/source-data/GeoIP2-Enterprise-Test.json +687 -0
  48. data/test/data/source-data/GeoIP2-ISP-Test.json +12593 -0
  49. data/test/data/source-data/GeoIP2-Precision-Enterprise-Test.json +2061 -0
  50. data/test/data/source-data/GeoIP2-Static-IP-Score-Test.json +2132 -0
  51. data/test/data/source-data/GeoIP2-User-Count-Test.json +2837 -0
  52. data/test/data/source-data/GeoLite2-ASN-Test.json +37 -0
  53. data/test/data/source-data/README +15 -0
  54. data/test/data/test-data/GeoIP2-Anonymous-IP-Test.mmdb +0 -0
  55. data/test/data/test-data/GeoIP2-City-Test-Broken-Double-Format.mmdb +0 -0
  56. data/test/data/test-data/GeoIP2-City-Test-Invalid-Node-Count.mmdb +0 -0
  57. data/test/data/test-data/GeoIP2-City-Test.mmdb +0 -0
  58. data/test/data/test-data/GeoIP2-Connection-Type-Test.mmdb +0 -0
  59. data/test/data/test-data/GeoIP2-Country-Test.mmdb +0 -0
  60. data/test/data/test-data/GeoIP2-DensityIncome-Test.mmdb +0 -0
  61. data/test/data/test-data/GeoIP2-Domain-Test.mmdb +0 -0
  62. data/test/data/test-data/GeoIP2-Enterprise-Test.mmdb +0 -0
  63. data/test/data/test-data/GeoIP2-ISP-Test.mmdb +0 -0
  64. data/test/data/test-data/GeoIP2-Precision-Enterprise-Test.mmdb +0 -0
  65. data/test/data/test-data/GeoIP2-Static-IP-Score-Test.mmdb +0 -0
  66. data/test/data/test-data/GeoIP2-User-Count-Test.mmdb +0 -0
  67. data/test/data/test-data/GeoLite2-ASN-Test.mmdb +0 -0
  68. data/test/data/test-data/MaxMind-DB-no-ipv4-search-tree.mmdb +0 -0
  69. data/test/data/test-data/MaxMind-DB-string-value-entries.mmdb +0 -0
  70. data/test/data/test-data/MaxMind-DB-test-broken-pointers-24.mmdb +0 -0
  71. data/test/data/test-data/MaxMind-DB-test-broken-search-tree-24.mmdb +0 -0
  72. data/test/data/test-data/MaxMind-DB-test-decoder.mmdb +0 -0
  73. data/test/data/test-data/MaxMind-DB-test-ipv4-24.mmdb +0 -0
  74. data/test/data/test-data/MaxMind-DB-test-ipv4-28.mmdb +0 -0
  75. data/test/data/test-data/MaxMind-DB-test-ipv4-32.mmdb +0 -0
  76. data/test/data/test-data/MaxMind-DB-test-ipv6-24.mmdb +0 -0
  77. data/test/data/test-data/MaxMind-DB-test-ipv6-28.mmdb +0 -0
  78. data/test/data/test-data/MaxMind-DB-test-ipv6-32.mmdb +0 -0
  79. data/test/data/test-data/MaxMind-DB-test-metadata-pointers.mmdb +0 -0
  80. data/test/data/test-data/MaxMind-DB-test-mixed-24.mmdb +0 -0
  81. data/test/data/test-data/MaxMind-DB-test-mixed-28.mmdb +0 -0
  82. data/test/data/test-data/MaxMind-DB-test-mixed-32.mmdb +0 -0
  83. data/test/data/test-data/MaxMind-DB-test-nested.mmdb +0 -0
  84. data/test/data/test-data/README.md +26 -0
  85. data/test/data/test-data/maps-with-pointers.raw +0 -0
  86. data/test/data/test-data/write-test-data.pl +641 -0
  87. data/test/data/tidyall.ini +5 -0
  88. data/test/test_model_country.rb +1 -1
  89. data/test/test_model_names.rb +1 -1
  90. data/test/test_reader.rb +79 -1
  91. metadata +85 -4
@@ -9,7 +9,7 @@ module MaxMind::GeoIP2::Model
9
9
  # fields in each record may be populated. See
10
10
  # https://dev.maxmind.com/geoip/geoip2/web-services for more details.
11
11
  #
12
- # See City for inherited methods.
12
+ # See {MaxMind::GeoIP2::Model::City} for inherited methods.
13
13
  class Enterprise < City
14
14
  end
15
15
  end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'maxmind/geoip2/model/abstract'
4
+
5
+ module MaxMind::GeoIP2::Model
6
+ # Model class for the GeoIP2 ISP database.
7
+ class ISP < Abstract
8
+ # The autonomous system number associated with the IP address.
9
+ #
10
+ # @return [Integer, nil]
11
+ def autonomous_system_number
12
+ get('autonomous_system_number')
13
+ end
14
+
15
+ # The organization associated with the registered autonomous system number
16
+ # for the IP address.
17
+ #
18
+ # @return [String, nil]
19
+ def autonomous_system_organization
20
+ get('autonomous_system_organization')
21
+ end
22
+
23
+ # The IP address that the data in the model is for.
24
+ #
25
+ # @return [String]
26
+ def ip_address
27
+ get('ip_address')
28
+ end
29
+
30
+ # The name of the ISP associated with the IP address.
31
+ #
32
+ # @return [String, nil]
33
+ def isp
34
+ get('isp')
35
+ end
36
+
37
+ # The network in CIDR notation associated with the record. In particular,
38
+ # this is the largest network where all of the fields besides ip_address
39
+ # have the same value.
40
+ #
41
+ # @return [String]
42
+ def network
43
+ get('network')
44
+ end
45
+
46
+ # The name of the organization associated with the IP address.
47
+ #
48
+ # @return [String, nil]
49
+ def organization
50
+ get('organization')
51
+ end
52
+ end
53
+ end
@@ -2,9 +2,14 @@
2
2
 
3
3
  require 'maxmind/db'
4
4
  require 'maxmind/geoip2/errors'
5
+ require 'maxmind/geoip2/model/anonymous_ip'
6
+ require 'maxmind/geoip2/model/asn'
5
7
  require 'maxmind/geoip2/model/city'
8
+ require 'maxmind/geoip2/model/connection_type'
6
9
  require 'maxmind/geoip2/model/country'
10
+ require 'maxmind/geoip2/model/domain'
7
11
  require 'maxmind/geoip2/model/enterprise'
12
+ require 'maxmind/geoip2/model/isp'
8
13
 
9
14
  module MaxMind::GeoIP2
10
15
  # Reader is a reader for the GeoIP2/GeoLite2 database format. IP addresses
@@ -31,29 +36,24 @@ module MaxMind::GeoIP2
31
36
  # threads. It is safe to use after forking only if you use
32
37
  # MaxMind::DB::MODE_MEMORY or if your version of Ruby supports IO#pread.
33
38
  #
34
- # Creating the Reader may raise an exception if initialization fails.
39
+ # @param database [String] a path to a GeoIP2/GeoLite2 database file.
35
40
  #
36
- # +database+ is a path to a GeoIP2/GeoLite2 database file.
41
+ # @param locales [Array<String>] a list of locale codes to use in the name
42
+ # property from most preferred to least preferred.
37
43
  #
38
- # +locales+ is a list of locale codes to use in the name property from most
39
- # preferred to least preferred.
44
+ # @param options [Hash<Symbol, Symbol>] options controlling the behavior of
45
+ # the Reader.
40
46
  #
41
- # +options+ is an option hash where each key is a symbol. The options
42
- # control the behavior of the Reader.
47
+ # @option options [Symbol] :mode Defines how to open the database. It may
48
+ # be one of MaxMind::DB::MODE_AUTO, MaxMind::DB::MODE_FILE, or
49
+ # MaxMind::DB::MODE_MEMORY. If you don't provide one, the Reader uses
50
+ # MaxMind::DB::MODE_AUTO. Refer to the definition of those constants in
51
+ # MaxMind::DB for an explanation of their meaning.
43
52
  #
44
- # The available options are:
53
+ # @raise [MaxMind::DB::InvalidDatabaseError] if the database is corrupt or
54
+ # invalid.
45
55
  #
46
- # [+:mode+] defines how to open the database. It may be one of
47
- # MaxMind::DB::MODE_AUTO, MaxMind::DB::MODE_FILE, or
48
- # MaxMind::DB::MODE_MEMORY. If you don't provide one, the Reader uses
49
- # MaxMind::DB::MODE_AUTO. Refer to the definition of those constants
50
- # in MaxMind::DB for an explanation of their meaning.
51
- #
52
- # === Exceptions
53
- #
54
- # Raises a MaxMind::DB::InvalidDatabaseError if the database is corrupt or
55
- # invalid. It can raise other exceptions, such as ArgumentError, if other
56
- # errors occur.
56
+ # @raise [ArgumentError] if the mode is invalid.
57
57
  def initialize(database, locales = ['en'], options = {})
58
58
  @reader = MaxMind::DB.new(database, options)
59
59
  @type = @reader.metadata.database_type
@@ -61,76 +61,178 @@ module MaxMind::GeoIP2
61
61
  @locales = locales
62
62
  end
63
63
 
64
- # Look up the +ip_address+ in the database and returns a
65
- # MaxMind::GeoIP2::Model::City object.
64
+ # Look up the IP address in the database.
65
+ #
66
+ # @param ip_address [String] a string in the standard notation. It may be
67
+ # IPv4 or IPv6.
68
+ #
69
+ # @return [MaxMind::GeoIP2::Model::AnonymousIP]
70
+ #
71
+ # @raise [ArgumentError] if used against a non-Anonymous IP database or if
72
+ # you attempt to look up an IPv6 address in an IPv4 only database.
73
+ #
74
+ # @raise [AddressNotFoundError] if the IP address is not found in the
75
+ # database.
76
+ #
77
+ # @raise [MaxMind::DB::InvalidDatabaseError] if the database appears
78
+ # corrupt.
79
+ def anonymous_ip(ip_address)
80
+ flat_model_for(
81
+ Model::AnonymousIP,
82
+ 'anonymous_ip',
83
+ 'GeoIP2-Anonymous-IP',
84
+ ip_address,
85
+ )
86
+ end
87
+
88
+ # Look up the IP address in an ASN database.
89
+ #
90
+ # @param ip_address [String] a string in the standard notation. It may be
91
+ # IPv4 or IPv6.
92
+ #
93
+ # @return [MaxMind::GeoIP2::Model::ASN]
66
94
  #
67
- # +ip_address+ is a string in the standard notation. It may be IPv4 or
68
- # IPv6.
95
+ # @raise [ArgumentError] if used against a non-ASN database or if you
96
+ # attempt to look up an IPv6 address in an IPv4 only database.
69
97
  #
70
- # === Exceptions
98
+ # @raise [AddressNotFoundError] if the IP address is not found in the
99
+ # database.
100
+ #
101
+ # @raise [MaxMind::DB::InvalidDatabaseError] if the database appears
102
+ # corrupt.
103
+ def asn(ip_address)
104
+ flat_model_for(Model::ASN, 'asn', 'GeoLite2-ASN', ip_address)
105
+ end
106
+
107
+ # Look up the IP address in a City database.
71
108
  #
72
- # Raises an ArgumentError if used against a non-City database or if you
73
- # attempt to look up an IPv6 address in an IPv4 only database.
109
+ # @param ip_address [String] a string in the standard notation. It may be
110
+ # IPv4 or IPv6.
74
111
  #
75
- # Raises an AddressNotFoundError if +ip_address+ is not found in the
76
- # database.
112
+ # @return [MaxMind::GeoIP2::Model::City]
77
113
  #
78
- # Raises a MaxMind::DB::InvalidDatabaseError if the database appears
79
- # corrupt.
114
+ # @raise [ArgumentError] if used against a non-City database or if you
115
+ # attempt to look up an IPv6 address in an IPv4 only database.
116
+ #
117
+ # @raise [AddressNotFoundError] if the IP address is not found in the
118
+ # database.
119
+ #
120
+ # @raise [MaxMind::DB::InvalidDatabaseError] if the database appears
121
+ # corrupt.
80
122
  def city(ip_address)
81
123
  model_for(Model::City, 'city', 'City', ip_address)
82
124
  end
83
125
 
84
- # Look up the +ip_address+ in the database and returns a
85
- # MaxMind::GeoIP2::Model::Country object.
126
+ # Look up the IP address in a Connection Type database.
127
+ #
128
+ # @param ip_address [String] a string in the standard notation. It may be
129
+ # IPv4 or IPv6.
130
+ #
131
+ # @return [MaxMind::GeoIP2::Model::ConnectionType]
86
132
  #
87
- # +ip_address+ is a string in the standard notation. It may be IPv4 or
88
- # IPv6.
133
+ # @raise [ArgumentError] if used against a non-Connection Type database or if
134
+ # you attempt to look up an IPv6 address in an IPv4 only database.
89
135
  #
90
- # === Exceptions
136
+ # @raise [AddressNotFoundError] if the IP address is not found in the
137
+ # database.
138
+ #
139
+ # @raise [MaxMind::DB::InvalidDatabaseError] if the database appears
140
+ # corrupt.
141
+ def connection_type(ip_address)
142
+ flat_model_for(
143
+ Model::ConnectionType,
144
+ 'connection_type',
145
+ 'GeoIP2-Connection-Type',
146
+ ip_address,
147
+ )
148
+ end
149
+
150
+ # Look up the IP address in a Country database.
91
151
  #
92
- # Raises an ArgumentError if used against a non-Country database or if you
93
- # attempt to look up an IPv6 address in an IPv4 only database.
152
+ # @param ip_address [String] a string in the standard notation. It may be
153
+ # IPv4 or IPv6.
94
154
  #
95
- # Raises an AddressNotFoundError if +ip_address+ is not found in the
96
- # database.
155
+ # @return [MaxMind::GeoIP2::Model::Country]
97
156
  #
98
- # Raises a MaxMind::DB::InvalidDatabaseError if the database appears
99
- # corrupt.
157
+ # @raise [ArgumentError] if used against a non-Country database or if you
158
+ # attempt to look up an IPv6 address in an IPv4 only database.
159
+ #
160
+ # @raise [AddressNotFoundError] if the IP address is not found in the
161
+ # database.
162
+ #
163
+ # @raise [MaxMind::DB::InvalidDatabaseError] if the database appears
164
+ # corrupt.
100
165
  def country(ip_address)
101
166
  model_for(Model::Country, 'country', 'Country', ip_address)
102
167
  end
103
168
 
104
- # Look up the +ip_address+ in the database and returns a
105
- # MaxMind::GeoIP2::Model::Enterprise object.
169
+ # Look up the IP address in a Domain database.
170
+ #
171
+ # @param ip_address [String] a string in the standard notation. It may be
172
+ # IPv4 or IPv6.
106
173
  #
107
- # +ip_address+ is a string in the standard notation. It may be IPv4 or
108
- # IPv6.
174
+ # @return [MaxMind::GeoIP2::Model::Domain]
109
175
  #
110
- # === Exceptions
176
+ # @raise [ArgumentError] if used against a non-Domain database or if you
177
+ # attempt to look up an IPv6 address in an IPv4 only database.
111
178
  #
112
- # Raises an ArgumentError if used against a non-Enterprise database or if
113
- # you attempt to look up an IPv6 address in an IPv4 only database.
179
+ # @raise [AddressNotFoundError] if the IP address is not found in the
180
+ # database.
181
+ #
182
+ # @raise [MaxMind::DB::InvalidDatabaseError] if the database appears
183
+ # corrupt.
184
+ def domain(ip_address)
185
+ flat_model_for(Model::Domain, 'domain', 'GeoIP2-Domain', ip_address)
186
+ end
187
+
188
+ # Look up the IP address in an Enterprise database.
114
189
  #
115
- # Raises an AddressNotFoundError if +ip_address+ is not found in the
116
- # database.
190
+ # @param ip_address [String] a string in the standard notation. It may be
191
+ # IPv4 or IPv6.
117
192
  #
118
- # Raises a MaxMind::DB::InvalidDatabaseError if the database appears
119
- # corrupt.
193
+ # @return [MaxMind::GeoIP2::Model::Enterprise]
194
+ #
195
+ # @raise [ArgumentError] if used against a non-Enterprise database or if
196
+ # you attempt to look up an IPv6 address in an IPv4 only database.
197
+ #
198
+ # @raise [AddressNotFoundError] if the IP address is not found in the
199
+ # database.
200
+ #
201
+ # @raise [MaxMind::DB::InvalidDatabaseError] if the database appears
202
+ # corrupt.
120
203
  def enterprise(ip_address)
121
204
  model_for(Model::Enterprise, 'enterprise', 'Enterprise', ip_address)
122
205
  end
123
206
 
124
- # Return the metadata associated with the database as a
125
- # MaxMind::DB::Metadata object.
207
+ # Look up the IP address in an ISP database.
208
+ #
209
+ # @param ip_address [String] a string in the standard notation. It may be
210
+ # IPv4 or IPv6.
211
+ #
212
+ # @return [MaxMind::GeoIP2::Model::ISP]
213
+ #
214
+ # @raise [ArgumentError] if used against a non-ISP database or if you
215
+ # attempt to look up an IPv6 address in an IPv4 only database.
216
+ #
217
+ # @raise [AddressNotFoundError] if the IP address is not found in the
218
+ # database.
219
+ #
220
+ # @raise [MaxMind::DB::InvalidDatabaseError] if the database appears
221
+ # corrupt.
222
+ def isp(ip_address)
223
+ flat_model_for(Model::ISP, 'isp', 'GeoIP2-ISP', ip_address)
224
+ end
225
+
226
+ # Return the metadata associated with the database.
227
+ #
228
+ # @return [MaxMind::DB::Metadata]
126
229
  def metadata
127
230
  @reader.metadata
128
231
  end
129
232
 
130
233
  # Close the Reader and return resources to the system.
131
234
  #
132
- # There is no useful return value. #close raises an exception if there is
133
- # an error.
235
+ # @return [void]
134
236
  def close
135
237
  @reader.close
136
238
  end
@@ -138,6 +240,16 @@ module MaxMind::GeoIP2
138
240
  private
139
241
 
140
242
  def model_for(model_class, method, type, ip_address)
243
+ record, prefix_length = get_record(method, type, ip_address)
244
+
245
+ record['traits'] = {} if !record.key?('traits')
246
+ record['traits']['ip_address'] = ip_address
247
+ record['traits']['prefix_length'] = prefix_length
248
+
249
+ model_class.new(record, @locales)
250
+ end
251
+
252
+ def get_record(method, type, ip_address)
141
253
  if !@type.include?(type)
142
254
  raise ArgumentError,
143
255
  "The #{method} method cannot be used with the #{@type} database."
@@ -150,11 +262,16 @@ module MaxMind::GeoIP2
150
262
  "The address #{ip_address} is not in the database."
151
263
  end
152
264
 
153
- record['traits'] = {} if !record.key?('traits')
154
- record['traits']['ip_address'] = ip_address
155
- record['traits']['prefix_length'] = prefix_length
265
+ [record, prefix_length]
266
+ end
156
267
 
157
- model_class.new(record, @locales)
268
+ def flat_model_for(model_class, method, type, ip_address)
269
+ record, prefix_length = get_record(method, type, ip_address)
270
+
271
+ record['ip_address'] = ip_address
272
+ record['prefix_length'] = prefix_length
273
+
274
+ model_class.new(record)
158
275
  end
159
276
  end
160
277
  end
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MaxMind::GeoIP2::Record
4
- class Abstract # :nodoc:
4
+ # @!visibility private
5
+ class Abstract
5
6
  def initialize(record)
6
7
  @record = record
7
8
  end
@@ -8,24 +8,29 @@ module MaxMind::GeoIP2::Record
8
8
  # This record is returned by all location services and databases besides
9
9
  # Country.
10
10
  #
11
- # See Place for inherited methods.
11
+ # See {MaxMind::GeoIP2::Record::Place} for inherited methods.
12
12
  class City < Place
13
13
  # A value from 0-100 indicating MaxMind's confidence that the city is
14
14
  # correct. This attribute is only available from the Insights service and
15
- # the GeoIP2 Enterprise database. Integer but may be nil.
15
+ # the GeoIP2 Enterprise database.
16
+ #
17
+ # @return [Integer, nil]
16
18
  def confidence
17
19
  get('confidence')
18
20
  end
19
21
 
20
22
  # The GeoName ID for the city. This attribute is returned by all location
21
- # services and databases. Integer but may be nil.
23
+ # services and databases.
24
+ #
25
+ # @return [Integer, nil]
22
26
  def geoname_id
23
27
  get('geoname_id')
24
28
  end
25
29
 
26
- # A Hash where the keys are locale codes (Strings) and the values are names
27
- # (Strings). This attribute is returned by all location services and
28
- # databases. Hash but may be nil.
30
+ # A Hash where the keys are locale codes and the values are names. This
31
+ # attribute is returned by all location services and databases.
32
+ #
33
+ # @return [Hash<String, String>, nil]
29
34
  def names
30
35
  get('names')
31
36
  end
@@ -7,24 +7,29 @@ module MaxMind::GeoIP2::Record
7
7
  #
8
8
  # This record is returned by all location services and databases.
9
9
  #
10
- # See Place for inherited methods.
10
+ # See {MaxMind::GeoIP2::Record::Place} for inherited methods.
11
11
  class Continent < Place
12
12
  # A two character continent code like "NA" (North America) or "OC"
13
13
  # (Oceania). This attribute is returned by all location services and
14
- # databases. String but may be nil.
14
+ # databases.
15
+ #
16
+ # @return [String, nil]
15
17
  def code
16
18
  get('code')
17
19
  end
18
20
 
19
21
  # The GeoName ID for the continent. This attribute is returned by all
20
- # location services and databases. String but may be nil.
22
+ # location services and databases.
23
+ #
24
+ # @return [String, nil]
21
25
  def geoname_id
22
26
  get('geoname_id')
23
27
  end
24
28
 
25
- # A Hash where the keys are locale codes (Strings) and the values are names
26
- # (Strings). This attribute is returned by all location services and
27
- # databases. Hash but may be nil.
29
+ # A Hash where the keys are locale codes and the values are names. This
30
+ # attribute is returned by all location services and databases.
31
+ #
32
+ # @return [Hash<String, String>, nil]
28
33
  def names
29
34
  get('names')
30
35
  end