maxmind-geoip2 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +28 -0
  3. data/Gemfile +12 -0
  4. data/Gemfile.lock +72 -0
  5. data/LICENSE-APACHE +202 -0
  6. data/LICENSE-MIT +17 -0
  7. data/README.dev.md +4 -0
  8. data/README.md +326 -0
  9. data/Rakefile +14 -0
  10. data/lib/maxmind/geoip2.rb +4 -0
  11. data/lib/maxmind/geoip2/client.rb +328 -0
  12. data/lib/maxmind/geoip2/errors.rb +41 -0
  13. data/lib/maxmind/geoip2/model/abstract.rb +31 -0
  14. data/lib/maxmind/geoip2/model/anonymous_ip.rb +67 -0
  15. data/lib/maxmind/geoip2/model/asn.rb +43 -0
  16. data/lib/maxmind/geoip2/model/city.rb +79 -0
  17. data/lib/maxmind/geoip2/model/connection_type.rb +36 -0
  18. data/lib/maxmind/geoip2/model/country.rb +74 -0
  19. data/lib/maxmind/geoip2/model/domain.rb +36 -0
  20. data/lib/maxmind/geoip2/model/enterprise.rb +19 -0
  21. data/lib/maxmind/geoip2/model/insights.rb +18 -0
  22. data/lib/maxmind/geoip2/model/isp.rb +57 -0
  23. data/lib/maxmind/geoip2/reader.rb +279 -0
  24. data/lib/maxmind/geoip2/record/abstract.rb +26 -0
  25. data/lib/maxmind/geoip2/record/city.rb +42 -0
  26. data/lib/maxmind/geoip2/record/continent.rb +41 -0
  27. data/lib/maxmind/geoip2/record/country.rb +58 -0
  28. data/lib/maxmind/geoip2/record/location.rb +77 -0
  29. data/lib/maxmind/geoip2/record/maxmind.rb +21 -0
  30. data/lib/maxmind/geoip2/record/place.rb +32 -0
  31. data/lib/maxmind/geoip2/record/postal.rb +34 -0
  32. data/lib/maxmind/geoip2/record/represented_country.rb +27 -0
  33. data/lib/maxmind/geoip2/record/subdivision.rb +52 -0
  34. data/lib/maxmind/geoip2/record/traits.rb +204 -0
  35. data/maxmind-geoip2.gemspec +26 -0
  36. data/test/test_client.rb +424 -0
  37. data/test/test_model_country.rb +80 -0
  38. data/test/test_model_names.rb +47 -0
  39. data/test/test_reader.rb +459 -0
  40. metadata +130 -0
@@ -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
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'maxmind/geoip2/model/country'
4
+ require 'maxmind/geoip2/record/city'
5
+ require 'maxmind/geoip2/record/location'
6
+ require 'maxmind/geoip2/record/postal'
7
+ require 'maxmind/geoip2/record/subdivision'
8
+
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
25
+
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
66
+
67
+ private
68
+
69
+ def create_subdivisions(subdivisions, locales)
70
+ return [] if subdivisions.nil?
71
+
72
+ subdivisions.map do |s|
73
+ MaxMind::GeoIP2::Record::Subdivision.new(s, locales)
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+ 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
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'maxmind/geoip2/record/continent'
4
+ require 'maxmind/geoip2/record/country'
5
+ require 'maxmind/geoip2/record/maxmind'
6
+ require 'maxmind/geoip2/record/represented_country'
7
+ require 'maxmind/geoip2/record/traits'
8
+
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
72
+ end
73
+ end
74
+ 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 Domain database.
9
+ class Domain < Abstract
10
+ # The second level domain associated with the IP address. This will be
11
+ # something like "example.com" or "example.co.uk", not "foo.example.com".
12
+ #
13
+ # @return [String, nil]
14
+ def domain
15
+ get('domain')
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
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'maxmind/geoip2/model/city'
4
+
5
+ module MaxMind
6
+ module GeoIP2
7
+ module Model
8
+ # Model class for the data returned by GeoIP2 Enterprise database lookups.
9
+ #
10
+ # The only difference between the City and Insights model classes is which
11
+ # fields in each record may be populated. See
12
+ # https://dev.maxmind.com/geoip/geoip2/web-services for more details.
13
+ #
14
+ # See {MaxMind::GeoIP2::Model::City} for inherited methods.
15
+ class Enterprise < City
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'maxmind/geoip2/model/city'
4
+
5
+ module MaxMind
6
+ module GeoIP2
7
+ module Model
8
+ # Model class for the data returned by the GeoIP2 Precision Insights web
9
+ # service.
10
+ #
11
+ # The only difference between the City and Insights model classes is which
12
+ # fields in each record may be populated. See
13
+ # https://dev.maxmind.com/geoip/geoip2/web-services for more details.
14
+ class Insights < City
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,57 @@
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 ISP database.
9
+ class ISP < 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 name of the ISP associated with the IP address.
33
+ #
34
+ # @return [String, nil]
35
+ def isp
36
+ get('isp')
37
+ end
38
+
39
+ # The network in CIDR notation associated with the record. In particular,
40
+ # this is the largest network where all of the fields besides ip_address
41
+ # have the same value.
42
+ #
43
+ # @return [String]
44
+ def network
45
+ get('network')
46
+ end
47
+
48
+ # The name of the organization associated with the IP address.
49
+ #
50
+ # @return [String, nil]
51
+ def organization
52
+ get('organization')
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,279 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'maxmind/db'
4
+ require 'maxmind/geoip2/errors'
5
+ require 'maxmind/geoip2/model/anonymous_ip'
6
+ require 'maxmind/geoip2/model/asn'
7
+ require 'maxmind/geoip2/model/city'
8
+ require 'maxmind/geoip2/model/connection_type'
9
+ require 'maxmind/geoip2/model/country'
10
+ require 'maxmind/geoip2/model/domain'
11
+ require 'maxmind/geoip2/model/enterprise'
12
+ require 'maxmind/geoip2/model/isp'
13
+
14
+ module MaxMind
15
+ module GeoIP2
16
+ # Reader is a reader for the GeoIP2/GeoLite2 database format. IP addresses
17
+ # can be looked up using the database specific methods.
18
+ #
19
+ # == Example
20
+ #
21
+ # require 'maxmind/geoip2'
22
+ #
23
+ # reader = MaxMind::GeoIP2::Reader.new('GeoIP2-Country.mmdb')
24
+ #
25
+ # record = reader.country('1.2.3.4')
26
+ # puts record.country.iso_code
27
+ #
28
+ # reader.close
29
+ class Reader
30
+ # Create a Reader for looking up IP addresses in a GeoIP2/GeoLite2 database
31
+ # file.
32
+ #
33
+ # If you're performing multiple lookups, it's most efficient to create one
34
+ # Reader and reuse it.
35
+ #
36
+ # Once created, the Reader is safe to use for lookups from multiple
37
+ # threads. It is safe to use after forking only if you use
38
+ # MaxMind::DB::MODE_MEMORY or if your version of Ruby supports IO#pread.
39
+ #
40
+ # @param database [String] a path to a GeoIP2/GeoLite2 database file.
41
+ #
42
+ # @param locales [Array<String>] a list of locale codes to use in the name
43
+ # property from most preferred to least preferred.
44
+ #
45
+ # @param options [Hash<Symbol, Symbol>] options controlling the behavior of
46
+ # the Reader.
47
+ #
48
+ # @option options [Symbol] :mode Defines how to open the database. It may
49
+ # be one of MaxMind::DB::MODE_AUTO, MaxMind::DB::MODE_FILE, or
50
+ # MaxMind::DB::MODE_MEMORY. If you don't provide one, the Reader uses
51
+ # MaxMind::DB::MODE_AUTO. Refer to the definition of those constants in
52
+ # MaxMind::DB for an explanation of their meaning.
53
+ #
54
+ # @raise [MaxMind::DB::InvalidDatabaseError] if the database is corrupt or
55
+ # invalid.
56
+ #
57
+ # @raise [ArgumentError] if the mode is invalid.
58
+ def initialize(database, locales = ['en'], options = {})
59
+ @reader = MaxMind::DB.new(database, options)
60
+ @type = @reader.metadata.database_type
61
+ locales = ['en'] if locales.empty?
62
+ @locales = locales
63
+ end
64
+
65
+ # Look up the IP address in the database.
66
+ #
67
+ # @param ip_address [String] a string in the standard notation. It may be
68
+ # IPv4 or IPv6.
69
+ #
70
+ # @return [MaxMind::GeoIP2::Model::AnonymousIP]
71
+ #
72
+ # @raise [ArgumentError] if used against a non-Anonymous IP database or if
73
+ # you attempt to look up an IPv6 address in an IPv4 only database.
74
+ #
75
+ # @raise [AddressNotFoundError] if the IP address is not found in the
76
+ # database.
77
+ #
78
+ # @raise [MaxMind::DB::InvalidDatabaseError] if the database appears
79
+ # corrupt.
80
+ def anonymous_ip(ip_address)
81
+ flat_model_for(
82
+ Model::AnonymousIP,
83
+ 'anonymous_ip',
84
+ 'GeoIP2-Anonymous-IP',
85
+ ip_address,
86
+ )
87
+ end
88
+
89
+ # Look up the IP address in an ASN database.
90
+ #
91
+ # @param ip_address [String] a string in the standard notation. It may be
92
+ # IPv4 or IPv6.
93
+ #
94
+ # @return [MaxMind::GeoIP2::Model::ASN]
95
+ #
96
+ # @raise [ArgumentError] if used against a non-ASN database or if you
97
+ # attempt to look up an IPv6 address in an IPv4 only database.
98
+ #
99
+ # @raise [AddressNotFoundError] if the IP address is not found in the
100
+ # database.
101
+ #
102
+ # @raise [MaxMind::DB::InvalidDatabaseError] if the database appears
103
+ # corrupt.
104
+ def asn(ip_address)
105
+ flat_model_for(Model::ASN, 'asn', 'GeoLite2-ASN', ip_address)
106
+ end
107
+
108
+ # Look up the IP address in a City database.
109
+ #
110
+ # @param ip_address [String] a string in the standard notation. It may be
111
+ # IPv4 or IPv6.
112
+ #
113
+ # @return [MaxMind::GeoIP2::Model::City]
114
+ #
115
+ # @raise [ArgumentError] if used against a non-City database or if you
116
+ # attempt to look up an IPv6 address in an IPv4 only database.
117
+ #
118
+ # @raise [AddressNotFoundError] if the IP address is not found in the
119
+ # database.
120
+ #
121
+ # @raise [MaxMind::DB::InvalidDatabaseError] if the database appears
122
+ # corrupt.
123
+ def city(ip_address)
124
+ model_for(Model::City, 'city', 'City', ip_address)
125
+ end
126
+
127
+ # Look up the IP address in a Connection Type database.
128
+ #
129
+ # @param ip_address [String] a string in the standard notation. It may be
130
+ # IPv4 or IPv6.
131
+ #
132
+ # @return [MaxMind::GeoIP2::Model::ConnectionType]
133
+ #
134
+ # @raise [ArgumentError] if used against a non-Connection Type database or if
135
+ # you attempt to look up an IPv6 address in an IPv4 only database.
136
+ #
137
+ # @raise [AddressNotFoundError] if the IP address is not found in the
138
+ # database.
139
+ #
140
+ # @raise [MaxMind::DB::InvalidDatabaseError] if the database appears
141
+ # corrupt.
142
+ def connection_type(ip_address)
143
+ flat_model_for(
144
+ Model::ConnectionType,
145
+ 'connection_type',
146
+ 'GeoIP2-Connection-Type',
147
+ ip_address,
148
+ )
149
+ end
150
+
151
+ # Look up the IP address in a Country database.
152
+ #
153
+ # @param ip_address [String] a string in the standard notation. It may be
154
+ # IPv4 or IPv6.
155
+ #
156
+ # @return [MaxMind::GeoIP2::Model::Country]
157
+ #
158
+ # @raise [ArgumentError] if used against a non-Country database or if you
159
+ # attempt to look up an IPv6 address in an IPv4 only database.
160
+ #
161
+ # @raise [AddressNotFoundError] if the IP address is not found in the
162
+ # database.
163
+ #
164
+ # @raise [MaxMind::DB::InvalidDatabaseError] if the database appears
165
+ # corrupt.
166
+ def country(ip_address)
167
+ model_for(Model::Country, 'country', 'Country', ip_address)
168
+ end
169
+
170
+ # Look up the IP address in a Domain database.
171
+ #
172
+ # @param ip_address [String] a string in the standard notation. It may be
173
+ # IPv4 or IPv6.
174
+ #
175
+ # @return [MaxMind::GeoIP2::Model::Domain]
176
+ #
177
+ # @raise [ArgumentError] if used against a non-Domain database or if you
178
+ # attempt to look up an IPv6 address in an IPv4 only database.
179
+ #
180
+ # @raise [AddressNotFoundError] if the IP address is not found in the
181
+ # database.
182
+ #
183
+ # @raise [MaxMind::DB::InvalidDatabaseError] if the database appears
184
+ # corrupt.
185
+ def domain(ip_address)
186
+ flat_model_for(Model::Domain, 'domain', 'GeoIP2-Domain', ip_address)
187
+ end
188
+
189
+ # Look up the IP address in an Enterprise database.
190
+ #
191
+ # @param ip_address [String] a string in the standard notation. It may be
192
+ # IPv4 or IPv6.
193
+ #
194
+ # @return [MaxMind::GeoIP2::Model::Enterprise]
195
+ #
196
+ # @raise [ArgumentError] if used against a non-Enterprise database or if
197
+ # you attempt to look up an IPv6 address in an IPv4 only database.
198
+ #
199
+ # @raise [AddressNotFoundError] if the IP address is not found in the
200
+ # database.
201
+ #
202
+ # @raise [MaxMind::DB::InvalidDatabaseError] if the database appears
203
+ # corrupt.
204
+ def enterprise(ip_address)
205
+ model_for(Model::Enterprise, 'enterprise', 'Enterprise', ip_address)
206
+ end
207
+
208
+ # Look up the IP address in an ISP database.
209
+ #
210
+ # @param ip_address [String] a string in the standard notation. It may be
211
+ # IPv4 or IPv6.
212
+ #
213
+ # @return [MaxMind::GeoIP2::Model::ISP]
214
+ #
215
+ # @raise [ArgumentError] if used against a non-ISP database or if you
216
+ # attempt to look up an IPv6 address in an IPv4 only database.
217
+ #
218
+ # @raise [AddressNotFoundError] if the IP address is not found in the
219
+ # database.
220
+ #
221
+ # @raise [MaxMind::DB::InvalidDatabaseError] if the database appears
222
+ # corrupt.
223
+ def isp(ip_address)
224
+ flat_model_for(Model::ISP, 'isp', 'GeoIP2-ISP', ip_address)
225
+ end
226
+
227
+ # Return the metadata associated with the database.
228
+ #
229
+ # @return [MaxMind::DB::Metadata]
230
+ def metadata
231
+ @reader.metadata
232
+ end
233
+
234
+ # Close the Reader and return resources to the system.
235
+ #
236
+ # @return [void]
237
+ def close
238
+ @reader.close
239
+ end
240
+
241
+ private
242
+
243
+ def model_for(model_class, method, type, ip_address)
244
+ record, prefix_length = get_record(method, type, ip_address)
245
+
246
+ record['traits'] = {} if !record.key?('traits')
247
+ record['traits']['ip_address'] = ip_address
248
+ record['traits']['prefix_length'] = prefix_length
249
+
250
+ model_class.new(record, @locales)
251
+ end
252
+
253
+ def get_record(method, type, ip_address)
254
+ if !@type.include?(type)
255
+ raise ArgumentError,
256
+ "The #{method} method cannot be used with the #{@type} database."
257
+ end
258
+
259
+ record, prefix_length = @reader.get_with_prefix_length(ip_address)
260
+
261
+ if record.nil?
262
+ raise AddressNotFoundError,
263
+ "The address #{ip_address} is not in the database."
264
+ end
265
+
266
+ [record, prefix_length]
267
+ end
268
+
269
+ def flat_model_for(model_class, method, type, ip_address)
270
+ record, prefix_length = get_record(method, type, ip_address)
271
+
272
+ record['ip_address'] = ip_address
273
+ record['prefix_length'] = prefix_length
274
+
275
+ model_class.new(record)
276
+ end
277
+ end
278
+ end
279
+ end