Skip to content

Add residential proxy data to anonymizer object#207

Merged
horgh merged 3 commits into
mainfrom
greg/stf-997-add-residential-to-anonymizer
Jul 16, 2026
Merged

Add residential proxy data to anonymizer object#207
horgh merged 3 commits into
mainfrom
greg/stf-997-add-residential-to-anonymizer

Conversation

@oschwald

@oschwald oschwald commented Jul 10, 2026

Copy link
Copy Markdown
Member

Summary

The GeoIP Insights web service is adding a residential sub-object to the anonymizer object. It contains residential proxy data for the network and may be populated even when no other anonymizer properties are set.

  • New reusable record for the feed shape (confidence, network_last_seen, provider_name) named AnonymizerFeed, so future anonymizer feeds can share it
  • New residential property on the Anonymizer record
  • Tests, fixtures, and changelog updated

Testing

bundle exec rake test and bundle exec rubocop pass.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added residential proxy details to GeoIP2 Insights anonymizer data, including confidence, provider name, and last-seen date.
    • Added support for accessing residential proxy information from Insights records.
  • Bug Fixes

    • Improved handling of missing last-seen dates by caching empty results, avoiding repeated lookups.
  • Tests

    • Added coverage for residential proxy data and anonymizer records with missing or partial information.

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: d927ab84-a6d5-42ca-9b90-f3579bc45163

📥 Commits

Reviewing files that changed from the base of the PR and between 537148d and f9d3fbc.

📒 Files selected for processing (7)
  • CHANGELOG.md
  • CLAUDE.md
  • lib/maxmind/geoip2/model/anonymous_plus.rb
  • lib/maxmind/geoip2/record/anonymizer.rb
  • lib/maxmind/geoip2/record/anonymizer_feed.rb
  • test/test_client.rb
  • test/test_record.rb

📝 Walkthrough

Walkthrough

The change adds residential proxy data to Insights anonymizer records, including confidence, provider name, and parsed last-seen dates. Missing network_last_seen values are now memoized, with tests, guidance, and release notes updated.

Changes

Anonymizer residential data

Layer / File(s) Summary
Residential record model and integration
lib/maxmind/geoip2/record/anonymizer_feed.rb, lib/maxmind/geoip2/record/anonymizer.rb, test/test_client.rb
Adds AnonymizerFeed and exposes residential anonymizer data through Anonymizer, with client fixture assertions for all three fields.
Missing-date memoization
lib/maxmind/geoip2/model/anonymous_plus.rb, lib/maxmind/geoip2/record/anonymizer.rb
Caches nil results when network_last_seen input is absent.
Coverage and implementation guidance
test/test_record.rb, CLAUDE.md, CHANGELOG.md
Adds missing-data coverage and documents the memoizing-nil pattern in the new 1.6.0 release notes and development guidance.

Estimated code review effort: 2 (Simple) | ~15 minutes

Sequence Diagram(s)

sequenceDiagram
  participant InsightsResponse
  participant Anonymizer
  participant AnonymizerFeed
  InsightsResponse->>Anonymizer: provide residential data
  Anonymizer->>AnonymizerFeed: wrap residential record
  AnonymizerFeed-->>Anonymizer: return residential fields
Loading

Poem

A rabbit hops through fields so neat,
Residential data joins the beat.
Dates parse softly, nils stay still,
Feeds bring provider names at will.
Tests thump their paws: all green!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding residential proxy data to the anonymizer object.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch greg/stf-997-add-residential-to-anonymizer

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new residential object (represented by the AnonymizerFeed class) to the anonymizer record in the GeoIP2 Insights model, allowing users to access residential proxy data such as confidence, provider name, and last seen date. The feedback suggests two improvements: using the safe navigation operator (&.) in Anonymizer#initialize for cleaner, more idiomatic Ruby code, and ensuring that nil values are correctly cached in AnonymizerFeed#network_last_seen to prevent redundant lookups when the date is missing.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread lib/maxmind/geoip2/record/anonymizer.rb
Comment thread lib/maxmind/geoip2/record/anonymizer_feed.rb
oschwald and others added 2 commits July 14, 2026 14:57
This adds a new residential sub-object to the anonymizer object in the
GeoIP2 Insights web service response. It includes a confidence score,
the provider name, and the date the network was last seen for
residential proxies.

The residential object may be populated even when no other anonymizer
attributes are set.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The network_last_seen methods memoized only successfully parsed dates.
When the value was unset, the defined? guard never became true, so
every call repeated the hash lookup instead of returning the cached
nil. Assign the instance variable in the nil branch as well so the
lookup runs at most once.

This fixes the newly added AnonymizerFeed#network_last_seen along with
the pre-existing instances of the same pattern in
Anonymizer#network_last_seen and AnonymousPlus#network_last_seen, and
updates the lazy-parsing examples in CLAUDE.md to match.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@oschwald
oschwald force-pushed the greg/stf-997-add-residential-to-anonymizer branch from 06ccfa9 to 39e1d6f Compare July 14, 2026 14:58
horgh
horgh previously approved these changes Jul 15, 2026

@horgh horgh left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. Claude had a couple comments but they seem unnecessary to me. I'll leave them in case you want to look at them.

def initialize(record)
super

@residential = AnonymizerFeed.new(record.nil? ? nil : record['residential'])

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test gap (major): the absent-residential and absent-anonymizer paths are untested. Insights#initialize always calls Anonymizer.new(record['anonymizer']), and most Insights responses carry no residential data (and non-Insights responses have no anonymizer at all), so Anonymizer.new(nil) / AnonymizerFeed.new(nil) are the common paths. This record.nil? ? nil : record['residential'] guard is the only thing preventing a NoMethodError, yet the sole fixture always fully populates residential.

Suggest adding a test with (a) an anonymizer that has only residential (the documented "may be populated even when no other anonymizer attributes are set" case) and (b) an anonymizer-less response, asserting residential is non-nil and its three fields return nil without raising. GeoIP2-php's InsightsTest.php has this exact case as a model.

— Claude, on behalf of Will

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude, on behalf of Greg: Added coverage in commit f9d3fbc (test/test_record.rb): test_insights_no_anonymizer builds a Model::Insights from a raw hash with no anonymizer key at all and asserts every anonymizer/anonymizer.residential getter returns nil with no NoMethodError, and test_insights_anonymizer_without_residential covers an anonymizer present without a nested residential key, asserting residential.confidence/.network_last_seen/.provider_name are all nil.


date_string = get('network_last_seen')

if !date_string

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test gap (major): this nil-date branch is untested — network_last_seen is only exercised with a valid date string. A residential feed with confidence/provider but no date is a normal payload; if this if !date_string guard regressed, Date.parse(nil) would raise. Note commit 39e1d6f ("Memoize nil results…") could be fully reverted and the suite would still pass.

Suggest asserting network_last_seen returns nil when absent (for the feed, top-level Anonymizer, and AnonymousPlus), and that a repeated call still returns nil to pin the memoization.

— Claude, on behalf of Will

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude, on behalf of Greg: Added coverage in commit f9d3fbc (test/test_record.rb): test_anonymizer_feed_network_last_seen_absent, test_anonymizer_network_last_seen_absent, and test_anonymous_plus_network_last_seen_absent each assert network_last_seen is nil (no Date.parse(nil) raise) when the date key is absent, covering Record::AnonymizerFeed, Record::Anonymizer, and Model::AnonymousPlus respectively. Verified the gap by temporarily removing the if !date_string guard in AnonymizerFeed#network_last_seen — 3 of the new tests failed with TypeError: no implicit conversion of nil into String, confirming they would catch a regression of this guard.

horgh's review of the anonymizer.residential addition flagged two
untested paths:

- Insights#initialize unconditionally calls
  Anonymizer.new(record['anonymizer']), and Anonymizer#initialize
  unconditionally calls AnonymizerFeed.new(record['residential']). The
  common case has neither key present, so Anonymizer.new(nil) and
  AnonymizerFeed.new(nil) are the hot paths, guarded only by
  `record.nil? ? nil : record['residential']`. Add coverage for a
  Model::Insights built from a raw hash with no "anonymizer" key at
  all, and for an "anonymizer" present without a nested "residential"
  key, asserting every getter returns nil with no NoMethodError.

- network_last_seen's `if !date_string` guard, which prevents
  Date.parse(nil) from raising when the date key is absent, was
  untested in all three places it is duplicated: AnonymizerFeed,
  Anonymizer, and Model::AnonymousPlus. Add a test per class
  asserting network_last_seen is nil when the date key is absent.

Verified the AnonymizerFeed test actually catches a regression: with
the guard temporarily removed (network_last_seen calling
Date.parse(date_string) unconditionally), 3 of the 5 new tests failed
with "TypeError: no implicit conversion of nil into String" as
expected. Restored the guard afterward.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@horgh
horgh merged commit fac0aab into main Jul 16, 2026
39 checks passed
@horgh
horgh deleted the greg/stf-997-add-residential-to-anonymizer branch July 16, 2026 14:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants