maxmind-geoip2 1.4.0 → 1.5.1

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.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/README.md +1 -1
  4. data/lib/maxmind/geoip2/record/traits.rb +9 -1
  5. data/lib/maxmind/geoip2/version.rb +1 -1
  6. metadata +9 -91
  7. data/CLAUDE.md +0 -390
  8. data/Gemfile +0 -5
  9. data/Gemfile.lock +0 -126
  10. data/README.dev.md +0 -4
  11. data/Rakefile +0 -14
  12. data/maxmind-geoip2.gemspec +0 -41
  13. data/test/data/LICENSE-APACHE +0 -202
  14. data/test/data/LICENSE-MIT +0 -17
  15. data/test/data/MaxMind-DB-spec.md +0 -573
  16. data/test/data/README.md +0 -11
  17. data/test/data/bad-data/README.md +0 -7
  18. data/test/data/bad-data/libmaxminddb/libmaxminddb-offset-integer-overflow.mmdb +0 -0
  19. data/test/data/bad-data/maxminddb-golang/cyclic-data-structure.mmdb +0 -0
  20. data/test/data/bad-data/maxminddb-golang/invalid-bytes-length.mmdb +0 -1
  21. data/test/data/bad-data/maxminddb-golang/invalid-data-record-offset.mmdb +0 -0
  22. data/test/data/bad-data/maxminddb-golang/invalid-map-key-length.mmdb +0 -0
  23. data/test/data/bad-data/maxminddb-golang/invalid-string-length.mmdb +0 -1
  24. data/test/data/bad-data/maxminddb-golang/metadata-is-an-uint128.mmdb +0 -1
  25. data/test/data/bad-data/maxminddb-golang/unexpected-bytes.mmdb +0 -0
  26. data/test/data/bad-data/maxminddb-python/bad-unicode-in-map-key.mmdb +0 -0
  27. data/test/data/cmd/write-test-data/main.go +0 -68
  28. data/test/data/go.mod +0 -13
  29. data/test/data/go.sum +0 -16
  30. data/test/data/pkg/writer/decoder.go +0 -178
  31. data/test/data/pkg/writer/geoip2.go +0 -184
  32. data/test/data/pkg/writer/ip.go +0 -39
  33. data/test/data/pkg/writer/maxmind.go +0 -246
  34. data/test/data/pkg/writer/nestedstructures.go +0 -73
  35. data/test/data/pkg/writer/writer.go +0 -61
  36. data/test/data/source-data/GeoIP-Anonymous-Plus-Test.json +0 -175
  37. data/test/data/source-data/GeoIP2-Anonymous-IP-Test.json +0 -55
  38. data/test/data/source-data/GeoIP2-City-Test.json +0 -13272
  39. data/test/data/source-data/GeoIP2-Connection-Type-Test.json +0 -127
  40. data/test/data/source-data/GeoIP2-Country-Test.json +0 -15978
  41. data/test/data/source-data/GeoIP2-DensityIncome-Test.json +0 -14
  42. data/test/data/source-data/GeoIP2-Domain-Test.json +0 -457
  43. data/test/data/source-data/GeoIP2-Enterprise-Test.json +0 -1110
  44. data/test/data/source-data/GeoIP2-IP-Risk-Test.json +0 -31
  45. data/test/data/source-data/GeoIP2-ISP-Test.json +0 -12605
  46. data/test/data/source-data/GeoIP2-Precision-Enterprise-Sandbox-Test.json +0 -296
  47. data/test/data/source-data/GeoIP2-Precision-Enterprise-Test.json +0 -3189
  48. data/test/data/source-data/GeoIP2-Static-IP-Score-Test.json +0 -2147
  49. data/test/data/source-data/GeoIP2-User-Count-Test.json +0 -2855
  50. data/test/data/source-data/GeoLite2-ASN-Test.json +0 -4120
  51. data/test/data/source-data/GeoLite2-City-Test.json +0 -12969
  52. data/test/data/source-data/GeoLite2-Country-Test.json +0 -11369
  53. data/test/data/test-data/GeoIP-Anonymous-Plus-Test.mmdb +0 -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-IP-Risk-Test.mmdb +0 -0
  64. data/test/data/test-data/GeoIP2-ISP-Test.mmdb +0 -0
  65. data/test/data/test-data/GeoIP2-Precision-Enterprise-Test.mmdb +0 -0
  66. data/test/data/test-data/GeoIP2-Static-IP-Score-Test.mmdb +0 -0
  67. data/test/data/test-data/GeoIP2-User-Count-Test.mmdb +0 -0
  68. data/test/data/test-data/GeoLite2-ASN-Test.mmdb +0 -0
  69. data/test/data/test-data/GeoLite2-City-Test.mmdb +0 -0
  70. data/test/data/test-data/GeoLite2-Country-Test.mmdb +0 -0
  71. data/test/data/test-data/MaxMind-DB-no-ipv4-search-tree.mmdb +0 -0
  72. data/test/data/test-data/MaxMind-DB-string-value-entries.mmdb +0 -0
  73. data/test/data/test-data/MaxMind-DB-test-broken-pointers-24.mmdb +0 -0
  74. data/test/data/test-data/MaxMind-DB-test-broken-search-tree-24.mmdb +0 -0
  75. data/test/data/test-data/MaxMind-DB-test-decoder.mmdb +0 -0
  76. data/test/data/test-data/MaxMind-DB-test-ipv4-24.mmdb +0 -0
  77. data/test/data/test-data/MaxMind-DB-test-ipv4-28.mmdb +0 -0
  78. data/test/data/test-data/MaxMind-DB-test-ipv4-32.mmdb +0 -0
  79. data/test/data/test-data/MaxMind-DB-test-ipv6-24.mmdb +0 -0
  80. data/test/data/test-data/MaxMind-DB-test-ipv6-28.mmdb +0 -0
  81. data/test/data/test-data/MaxMind-DB-test-ipv6-32.mmdb +0 -0
  82. data/test/data/test-data/MaxMind-DB-test-metadata-pointers.mmdb +0 -0
  83. data/test/data/test-data/MaxMind-DB-test-mixed-24.mmdb +0 -0
  84. data/test/data/test-data/MaxMind-DB-test-mixed-28.mmdb +0 -0
  85. data/test/data/test-data/MaxMind-DB-test-mixed-32.mmdb +0 -0
  86. data/test/data/test-data/MaxMind-DB-test-nested.mmdb +0 -0
  87. data/test/data/test-data/MaxMind-DB-test-pointer-decoder.mmdb +0 -0
  88. data/test/data/test-data/README.md +0 -42
  89. data/test/data/test-data/maps-with-pointers.raw +0 -0
  90. data/test/data/tidyall.ini +0 -5
  91. data/test/test_client.rb +0 -467
  92. data/test/test_model_country.rb +0 -95
  93. data/test/test_model_names.rb +0 -50
  94. data/test/test_reader.rb +0 -589
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f26229b50b6ba4760df9389e76c5e705dc2b5b53e7fc50eb6be25d2af74f6985
4
- data.tar.gz: bfcb0fef72edaf05cdfcb1cc55be5ce2d12afbc650912e062ae263649a279736
3
+ metadata.gz: 101e87b30523d5d5ff9649bb1d379d0ea3d198a11ea4d989750c62bb15872cb2
4
+ data.tar.gz: 5c2580f874e9902dff611d5c408521f9486074db67d99ed68cbeb6d631ebe606
5
5
  SHA512:
6
- metadata.gz: 4d3de90ee7df88d6acbef1af76202af2130e9670ad726bea5f9753581bd5e3ae962f859720458f833731f0822cc08345171ac90cde7b446c784ca7c6ca21215c
7
- data.tar.gz: 34b7484739814ecd6de33435310c8cb29840534c4beed8d063c2ed00f2e0eee46338cec95bef1be5acb2ac2947be937842a2edc1f646b46460d70fa656213f6d
6
+ metadata.gz: 609a302c0c3f4d7087df0531ce26c643412a2c7c4c2d92366ebe8cf26fae8b5bd04b8b15bc6b6a0f5285fcf15e3b74dbd92cc3e63e697e308431c9660598904f
7
+ data.tar.gz: 91115ba0d2bf0868bec4644c58ac12c26f94e5ee1b55b63592e05fb7e1a3461251ab078fa709f684cc3166db3509737f68edc67a3f536674d2b235325cad61b4
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.5.1 (2026-01-19)
4
+
5
+ * Re-release with a fix to the release process. This includes a bump of the
6
+ gem's version in `Gemfile.lock`.
7
+
8
+ ## 1.5.0 (2026-01-19)
9
+
10
+ * Unnecessary files were removed from the published .gem. Pull request by
11
+ Orien Madgwick. GitHub #131.
12
+ * Updated `connection_pool` dependency to allow version 3+. Reported by
13
+ Igor Kasyanchuk. GitHub #140.
14
+
3
15
  ## 1.4.0 (2025-11-20)
4
16
 
5
17
  * Ruby 3.2+ is now required. If you're using Ruby 3.0 or 3.1, please use
data/README.md CHANGED
@@ -360,7 +360,7 @@ This library uses [Semantic Versioning](https://semver.org/).
360
360
 
361
361
  ## Copyright and License
362
362
 
363
- This software is Copyright (c) 2020-2025 by MaxMind, Inc.
363
+ This software is Copyright (c) 2020-2026 by MaxMind, Inc.
364
364
 
365
365
  This is free software, licensed under the [Apache License, Version
366
366
  2.0](LICENSE-APACHE) or the [MIT License](LICENSE-MIT), at your option.
@@ -242,7 +242,15 @@ module MaxMind
242
242
  # services is more static than the IP risk score provided in minFraud
243
243
  # and is not responsive to traffic on your network. If you need realtime
244
244
  # IP risk scoring based on behavioral signals on your own network, please
245
- # use minFraud. This property is only available from Insights.
245
+ # use minFraud.
246
+ #
247
+ # We do not provide an IP risk snapshot for low-risk networks. If this
248
+ # field is not populated, we either do not have signals for the network
249
+ # or the signals we have show that the network is low-risk. If you would
250
+ # like to get signals for low-risk networks, please use the minFraud web
251
+ # services.
252
+ #
253
+ # This property is only available from Insights.
246
254
  #
247
255
  # @return [Float, nil]
248
256
  def ip_risk_snapshot
@@ -3,6 +3,6 @@
3
3
  module MaxMind
4
4
  module GeoIP2
5
5
  # The Gem version.
6
- VERSION = '1.4.0'
6
+ VERSION = '1.5.1'
7
7
  end
8
8
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: maxmind-geoip2
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - William Storey
@@ -13,16 +13,22 @@ dependencies:
13
13
  name: connection_pool
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
- - - "~>"
16
+ - - ">="
17
17
  - !ruby/object:Gem::Version
18
18
  version: '2.2'
19
+ - - "<"
20
+ - !ruby/object:Gem::Version
21
+ version: '4.0'
19
22
  type: :runtime
20
23
  prerelease: false
21
24
  version_requirements: !ruby/object:Gem::Requirement
22
25
  requirements:
23
- - - "~>"
26
+ - - ">="
24
27
  - !ruby/object:Gem::Version
25
28
  version: '2.2'
29
+ - - "<"
30
+ - !ruby/object:Gem::Version
31
+ version: '4.0'
26
32
  - !ruby/object:Gem::Dependency
27
33
  name: http
28
34
  requirement: !ruby/object:Gem::Requirement
@@ -177,14 +183,9 @@ extensions: []
177
183
  extra_rdoc_files: []
178
184
  files:
179
185
  - CHANGELOG.md
180
- - CLAUDE.md
181
- - Gemfile
182
- - Gemfile.lock
183
186
  - LICENSE-APACHE
184
187
  - LICENSE-MIT
185
- - README.dev.md
186
188
  - README.md
187
- - Rakefile
188
189
  - lib/maxmind/geoip2.rb
189
190
  - lib/maxmind/geoip2/client.rb
190
191
  - lib/maxmind/geoip2/errors.rb
@@ -213,89 +214,6 @@ files:
213
214
  - lib/maxmind/geoip2/record/subdivision.rb
214
215
  - lib/maxmind/geoip2/record/traits.rb
215
216
  - lib/maxmind/geoip2/version.rb
216
- - maxmind-geoip2.gemspec
217
- - test/data/LICENSE-APACHE
218
- - test/data/LICENSE-MIT
219
- - test/data/MaxMind-DB-spec.md
220
- - test/data/README.md
221
- - test/data/bad-data/README.md
222
- - test/data/bad-data/libmaxminddb/libmaxminddb-offset-integer-overflow.mmdb
223
- - test/data/bad-data/maxminddb-golang/cyclic-data-structure.mmdb
224
- - test/data/bad-data/maxminddb-golang/invalid-bytes-length.mmdb
225
- - test/data/bad-data/maxminddb-golang/invalid-data-record-offset.mmdb
226
- - test/data/bad-data/maxminddb-golang/invalid-map-key-length.mmdb
227
- - test/data/bad-data/maxminddb-golang/invalid-string-length.mmdb
228
- - test/data/bad-data/maxminddb-golang/metadata-is-an-uint128.mmdb
229
- - test/data/bad-data/maxminddb-golang/unexpected-bytes.mmdb
230
- - test/data/bad-data/maxminddb-python/bad-unicode-in-map-key.mmdb
231
- - test/data/cmd/write-test-data/main.go
232
- - test/data/go.mod
233
- - test/data/go.sum
234
- - test/data/pkg/writer/decoder.go
235
- - test/data/pkg/writer/geoip2.go
236
- - test/data/pkg/writer/ip.go
237
- - test/data/pkg/writer/maxmind.go
238
- - test/data/pkg/writer/nestedstructures.go
239
- - test/data/pkg/writer/writer.go
240
- - test/data/source-data/GeoIP-Anonymous-Plus-Test.json
241
- - test/data/source-data/GeoIP2-Anonymous-IP-Test.json
242
- - test/data/source-data/GeoIP2-City-Test.json
243
- - test/data/source-data/GeoIP2-Connection-Type-Test.json
244
- - test/data/source-data/GeoIP2-Country-Test.json
245
- - test/data/source-data/GeoIP2-DensityIncome-Test.json
246
- - test/data/source-data/GeoIP2-Domain-Test.json
247
- - test/data/source-data/GeoIP2-Enterprise-Test.json
248
- - test/data/source-data/GeoIP2-IP-Risk-Test.json
249
- - test/data/source-data/GeoIP2-ISP-Test.json
250
- - test/data/source-data/GeoIP2-Precision-Enterprise-Sandbox-Test.json
251
- - test/data/source-data/GeoIP2-Precision-Enterprise-Test.json
252
- - test/data/source-data/GeoIP2-Static-IP-Score-Test.json
253
- - test/data/source-data/GeoIP2-User-Count-Test.json
254
- - test/data/source-data/GeoLite2-ASN-Test.json
255
- - test/data/source-data/GeoLite2-City-Test.json
256
- - test/data/source-data/GeoLite2-Country-Test.json
257
- - test/data/test-data/GeoIP-Anonymous-Plus-Test.mmdb
258
- - test/data/test-data/GeoIP2-Anonymous-IP-Test.mmdb
259
- - test/data/test-data/GeoIP2-City-Test-Broken-Double-Format.mmdb
260
- - test/data/test-data/GeoIP2-City-Test-Invalid-Node-Count.mmdb
261
- - test/data/test-data/GeoIP2-City-Test.mmdb
262
- - test/data/test-data/GeoIP2-Connection-Type-Test.mmdb
263
- - test/data/test-data/GeoIP2-Country-Test.mmdb
264
- - test/data/test-data/GeoIP2-DensityIncome-Test.mmdb
265
- - test/data/test-data/GeoIP2-Domain-Test.mmdb
266
- - test/data/test-data/GeoIP2-Enterprise-Test.mmdb
267
- - test/data/test-data/GeoIP2-IP-Risk-Test.mmdb
268
- - test/data/test-data/GeoIP2-ISP-Test.mmdb
269
- - test/data/test-data/GeoIP2-Precision-Enterprise-Test.mmdb
270
- - test/data/test-data/GeoIP2-Static-IP-Score-Test.mmdb
271
- - test/data/test-data/GeoIP2-User-Count-Test.mmdb
272
- - test/data/test-data/GeoLite2-ASN-Test.mmdb
273
- - test/data/test-data/GeoLite2-City-Test.mmdb
274
- - test/data/test-data/GeoLite2-Country-Test.mmdb
275
- - test/data/test-data/MaxMind-DB-no-ipv4-search-tree.mmdb
276
- - test/data/test-data/MaxMind-DB-string-value-entries.mmdb
277
- - test/data/test-data/MaxMind-DB-test-broken-pointers-24.mmdb
278
- - test/data/test-data/MaxMind-DB-test-broken-search-tree-24.mmdb
279
- - test/data/test-data/MaxMind-DB-test-decoder.mmdb
280
- - test/data/test-data/MaxMind-DB-test-ipv4-24.mmdb
281
- - test/data/test-data/MaxMind-DB-test-ipv4-28.mmdb
282
- - test/data/test-data/MaxMind-DB-test-ipv4-32.mmdb
283
- - test/data/test-data/MaxMind-DB-test-ipv6-24.mmdb
284
- - test/data/test-data/MaxMind-DB-test-ipv6-28.mmdb
285
- - test/data/test-data/MaxMind-DB-test-ipv6-32.mmdb
286
- - test/data/test-data/MaxMind-DB-test-metadata-pointers.mmdb
287
- - test/data/test-data/MaxMind-DB-test-mixed-24.mmdb
288
- - test/data/test-data/MaxMind-DB-test-mixed-28.mmdb
289
- - test/data/test-data/MaxMind-DB-test-mixed-32.mmdb
290
- - test/data/test-data/MaxMind-DB-test-nested.mmdb
291
- - test/data/test-data/MaxMind-DB-test-pointer-decoder.mmdb
292
- - test/data/test-data/README.md
293
- - test/data/test-data/maps-with-pointers.raw
294
- - test/data/tidyall.ini
295
- - test/test_client.rb
296
- - test/test_model_country.rb
297
- - test/test_model_names.rb
298
- - test/test_reader.rb
299
217
  homepage: https://github.com/maxmind/GeoIP2-ruby
300
218
  licenses:
301
219
  - Apache-2.0
data/CLAUDE.md DELETED
@@ -1,390 +0,0 @@
1
- # CLAUDE.md
2
-
3
- This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
-
5
- ## Project Overview
6
-
7
- **GeoIP2-ruby** is MaxMind's official Ruby client library for:
8
- - **GeoIP2/GeoLite2 Web Services**: Country, City, and Insights endpoints
9
- - **GeoIP2/GeoLite2 Databases**: Local MMDB file reading for various database types (City, Country, ASN, Anonymous IP, Anonymous Plus, ISP, etc.)
10
-
11
- The library provides both web service clients and database readers that return strongly-typed model objects containing geographic, ISP, anonymizer, and other IP-related data.
12
-
13
- **Key Technologies:**
14
- - Ruby 3.2+ (uses frozen string literals and modern Ruby features)
15
- - MaxMind DB Reader for binary database files
16
- - HTTP gem for web service client functionality
17
- - Minitest for testing
18
- - RuboCop with multiple plugins for code quality
19
-
20
- ## Code Architecture
21
-
22
- ### Package Structure
23
-
24
- ```
25
- lib/maxmind/geoip2/
26
- ├── model/ # Response models (City, Insights, AnonymousIP, etc.)
27
- ├── record/ # Data records (City, Location, Traits, etc.)
28
- ├── client.rb # HTTP client for MaxMind web services
29
- ├── reader.rb # Local MMDB file reader
30
- ├── errors.rb # Custom exceptions for error handling
31
- └── version.rb # Version constant
32
- ```
33
-
34
- ### Key Design Patterns
35
-
36
- #### 1. **Attr Reader Pattern for Immutable Data**
37
-
38
- Models expose data through `attr_reader` attributes that are initialized in the constructor. Unlike PHP's readonly properties, Ruby uses instance variables with attr_reader:
39
-
40
- ```ruby
41
- class City < Country
42
- attr_reader :city
43
- attr_reader :location
44
- attr_reader :postal
45
- attr_reader :subdivisions
46
-
47
- def initialize(record, locales)
48
- super
49
- @city = MaxMind::GeoIP2::Record::City.new(record['city'], locales)
50
- @location = MaxMind::GeoIP2::Record::Location.new(record['location'])
51
- @postal = MaxMind::GeoIP2::Record::Postal.new(record['postal'])
52
- @subdivisions = create_subdivisions(record['subdivisions'], locales)
53
- end
54
- end
55
- ```
56
-
57
- **Key Points:**
58
- - Instance variables are set in the constructor
59
- - Use `attr_reader` to expose them
60
- - Models and records are initialized from hash data (from JSON/DB)
61
- - Records are composed objects (City contains City record, Location record, etc.)
62
-
63
- #### 2. **Inheritance Hierarchies**
64
-
65
- Models follow clear inheritance patterns:
66
- - `Country` → base model with country/continent data
67
- - `City` extends `Country` → adds city, location, postal, subdivisions
68
- - `Insights` extends `City` → adds additional web service fields (web service only)
69
- - `Enterprise` extends `City` → adds enterprise-specific fields
70
-
71
- Records have similar patterns:
72
- - `Abstract` → base with `get` method for accessing hash data
73
- - `Place` extends `Abstract` → adds names/locales handling
74
- - Specific records (`City`, `Country`, etc.) extend `Place` or `Abstract`
75
-
76
- #### 3. **Get Method Pattern for Data Access**
77
-
78
- Both models and records use a protected `get` method to safely access hash data:
79
-
80
- ```ruby
81
- def get(key)
82
- if @record.nil? || !@record.key?(key)
83
- return false if key.start_with?('is_')
84
- return nil
85
- end
86
-
87
- @record[key]
88
- end
89
- ```
90
-
91
- - Returns `false` for missing boolean fields (starting with `is_`)
92
- - Returns `nil` for missing optional fields
93
- - Records store the raw hash in `@record` instance variable
94
-
95
- Public methods expose data through the `get` method:
96
-
97
- ```ruby
98
- def anonymizer_confidence
99
- get('anonymizer_confidence')
100
- end
101
-
102
- def provider_name
103
- get('provider_name')
104
- end
105
- ```
106
-
107
- #### 4. **Lazy Parsing for Special Types**
108
-
109
- Some fields require parsing and are computed lazily:
110
-
111
- ```ruby
112
- def network_last_seen
113
- return @network_last_seen if defined?(@network_last_seen)
114
-
115
- date_string = get('network_last_seen')
116
-
117
- if !date_string
118
- return nil
119
- end
120
-
121
- @network_last_seen = Date.parse(date_string)
122
- end
123
- ```
124
-
125
- - Use `defined?(@variable)` to check if already parsed
126
- - Parse only once and cache in instance variable
127
- - Handle nil cases before parsing
128
-
129
- #### 5. **Web Service Only vs Database Models**
130
-
131
- Some models are only used by web services and do **not** need MaxMind DB support:
132
-
133
- **Web Service Only Models**:
134
- - Models that are exclusive to web service responses
135
- - Simpler implementation, just inherit and define in model hierarchy
136
- - Example: `Insights` (extends City but used only for web service)
137
-
138
- **Database-Supported Models**:
139
- - Models used by both web services and database files
140
- - Reader has specific methods (e.g., `anonymous_ip`, `anonymous_plus`, `city`)
141
- - Must handle MaxMind DB format data structures
142
- - Example: `City`, `Country`, `AnonymousIP`, `AnonymousPlus`
143
-
144
- ## Testing Conventions
145
-
146
- ### Running Tests
147
-
148
- ```bash
149
- # Install dependencies
150
- bundle install
151
-
152
- # Run all tests
153
- bundle exec rake test
154
-
155
- # Run tests and RuboCop
156
- bundle exec rake # default task
157
-
158
- # Run RuboCop only
159
- bundle exec rake rubocop
160
-
161
- # Run specific test file
162
- ruby -Ilib:test test/test_reader.rb
163
- ```
164
-
165
- ### Test Structure
166
-
167
- Tests are organized by functionality:
168
- - `test/test_reader.rb` - Database reader tests
169
- - `test/test_client.rb` - Web service client tests
170
- - `test/test_model_*.rb` - Model-specific tests
171
- - `test/data/` - Test fixtures and sample database files
172
-
173
- ### Test Patterns
174
-
175
- Tests use Minitest with a constant for test data:
176
-
177
- ```ruby
178
- class CountryModelTest < Minitest::Test
179
- RAW = {
180
- 'continent' => {
181
- 'code' => 'NA',
182
- 'geoname_id' => 42,
183
- 'names' => { 'en' => 'North America' },
184
- },
185
- 'country' => {
186
- 'geoname_id' => 1,
187
- 'iso_code' => 'US',
188
- 'names' => { 'en' => 'United States of America' },
189
- },
190
- 'traits' => {
191
- 'ip_address' => '1.2.3.4',
192
- 'prefix_length' => 24,
193
- },
194
- }.freeze
195
-
196
- def test_values
197
- model = MaxMind::GeoIP2::Model::Country.new(RAW, ['en'])
198
-
199
- assert_equal(42, model.continent.geoname_id)
200
- assert_equal('NA', model.continent.code)
201
- assert_equal('United States of America', model.country.name)
202
- end
203
- end
204
- ```
205
-
206
- When adding new fields to models:
207
- 1. Update the `RAW` constant to include the new field
208
- 2. Add assertions to verify the field is properly populated
209
- 3. Test both presence and absence of the field (nil handling)
210
- 4. Test with different values if applicable
211
-
212
- ## Working with This Codebase
213
-
214
- ### Adding New Fields to Existing Models
215
-
216
- For database models (like AnonymousPlus):
217
-
218
- 1. **Add a public method** that calls `get`:
219
- ```ruby
220
- # A description of the field.
221
- #
222
- # @return [Type, nil]
223
- def field_name
224
- get('field_name')
225
- end
226
- ```
227
-
228
- 2. **For fields requiring parsing** (dates, complex types), use lazy loading:
229
- ```ruby
230
- def network_last_seen
231
- return @network_last_seen if defined?(@network_last_seen)
232
-
233
- date_string = get('network_last_seen')
234
-
235
- if !date_string
236
- return nil
237
- end
238
-
239
- @network_last_seen = Date.parse(date_string)
240
- end
241
- ```
242
-
243
- For composed models (like City, Country):
244
-
245
- 1. **Add `attr_reader`** for the new record/field:
246
- ```ruby
247
- attr_reader :new_field
248
- ```
249
-
250
- 2. **Initialize in constructor**:
251
- ```ruby
252
- def initialize(record, locales)
253
- super
254
- @new_field = record['new_field']
255
- end
256
- ```
257
-
258
- 3. **Provide comprehensive YARD documentation** (`@return` tags)
259
- 4. **Update tests** to include the new field in test data and assertions
260
- 5. **Update CHANGELOG.md** with the change
261
-
262
- ### Adding New Models
263
-
264
- When creating a new model class:
265
-
266
- 1. **Determine if web service only or database-supported**
267
- 2. **Follow the pattern** from existing similar models
268
- 3. **Extend the appropriate base class** (e.g., `Country`, `City`, or standalone)
269
- 4. **Use `attr_reader`** for composed record objects
270
- 5. **Provide comprehensive YARD documentation** for all public methods
271
- 6. **Add corresponding tests** with full coverage
272
- 7. **If database-supported**, add a method to `Reader` class
273
-
274
- ### Deprecation Guidelines
275
-
276
- When deprecating fields:
277
-
278
- 1. **Use `@deprecated` in YARD doc** with version and alternative:
279
- ```ruby
280
- # This field is deprecated as of version 2.0.0.
281
- # Use the anonymizer object from the Insights response instead.
282
- #
283
- # @return [Boolean]
284
- # @deprecated since 2.0.0
285
- def is_anonymous
286
- get('is_anonymous')
287
- end
288
- ```
289
-
290
- 2. **Keep deprecated fields functional** - don't break existing code
291
- 3. **Update CHANGELOG.md** with deprecation notices
292
- 4. **Document alternatives** in the deprecation message
293
-
294
- ### CHANGELOG.md Format
295
-
296
- Always update `CHANGELOG.md` for user-facing changes.
297
-
298
- **Important**: Do not add a date to changelog entries until release time.
299
-
300
- - If there's an existing version entry without a date (e.g., `1.5.0`), add your changes there
301
- - If creating a new version entry, don't include a date - it will be added at release time
302
- - Use past tense for descriptions
303
-
304
- ```markdown
305
- ## 1.5.0
306
-
307
- * A new `field_name` method has been added to `MaxMind::GeoIP2::Model::ModelName`.
308
- This method provides information about...
309
- * The `old_field` method in `MaxMind::GeoIP2::Model::ModelName` has been deprecated.
310
- Please use `new_field` instead.
311
- ```
312
-
313
- ## Common Pitfalls and Solutions
314
-
315
- ### Problem: Incorrect Nil Handling
316
-
317
- Using the wrong nil check can cause unexpected behavior.
318
-
319
- **Solution**: Follow these patterns:
320
- - Use `if !variable` or `if variable.nil?` to check for nil
321
- - The `get` method returns `nil` for missing keys (except `is_*` keys which return `false`)
322
- - Use `defined?(@variable)` to check if an instance variable has been set (for lazy loading)
323
-
324
- ### Problem: Missing YARD Documentation
325
-
326
- New methods without documentation make the API harder to use.
327
-
328
- **Solution**: Always add YARD documentation:
329
- - Use `@return [Type, nil]` for the return type
330
- - Add a description of what the method returns
331
- - Use `@deprecated since X.Y.Z` for deprecated methods
332
- - Include examples in model class documentation if helpful
333
-
334
- ### Problem: Test Failures After Adding Fields
335
-
336
- Tests fail because fixtures don't include new fields.
337
-
338
- **Solution**: Update all related tests:
339
- 1. Add field to test `RAW` constant or test data hash
340
- 2. Add assertions for the new field
341
- 3. Test nil case if field is optional
342
- 4. Test different data types if applicable
343
-
344
- ## Code Style Requirements
345
-
346
- - **RuboCop enforced** with multiple plugins (minitest, performance, rake, thread_safety)
347
- - **Frozen string literals** (`# frozen_string_literal: true`) in all files
348
- - **Target Ruby 3.2+**
349
- - **No metrics cops** - AbcSize, ClassLength, MethodLength disabled
350
- - **Trailing commas allowed** in arrays, hashes, and arguments
351
- - **Use `if !condition`** instead of `unless condition` (NegatedIf disabled)
352
-
353
- Key RuboCop configurations:
354
- - Line length not enforced
355
- - Format string token checks disabled
356
- - Numeric predicates allowed in any style
357
- - Multiple assertions allowed in tests
358
-
359
- ## Development Workflow
360
-
361
- ### Setup
362
- ```bash
363
- bundle install
364
- ```
365
-
366
- ### Before Committing
367
- ```bash
368
- # Run tests and linting
369
- bundle exec rake
370
-
371
- # Or run separately
372
- bundle exec rake test
373
- bundle exec rake rubocop
374
- ```
375
-
376
- ### Running Single Test
377
- ```bash
378
- ruby -Ilib:test test/test_reader.rb
379
- ```
380
-
381
- ### Version Requirements
382
- - **Ruby 3.2+** required
383
- - Target compatibility should match current supported Ruby versions (3.2-3.4)
384
-
385
- ## Additional Resources
386
-
387
- - [API Documentation](https://www.rubydoc.info/gems/maxmind-geoip2)
388
- - [GeoIP2 Web Services Docs](https://dev.maxmind.com/geoip/docs/web-services)
389
- - [MaxMind DB Format](https://maxmind.github.io/MaxMind-DB/)
390
- - GitHub Issues: https://github.com/maxmind/GeoIP2-ruby/issues
data/Gemfile DELETED
@@ -1,5 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- source 'https://rubygems.org'
4
-
5
- gemspec