I spent some of today debugging an error that suddenly started appearing in CI runs for unit tests:
NoMethodError:
undefined method `present?' for nil:NilClass
return if config[:license_type].present?
^^^^^^^^^
Having prior experiences with code that was written for a Ruby only project but happened to rely on a Rails dependency, I pretty quickly knew why it was breaking: NilClass#present? is an ActiveSupport extension to Ruby, not part of the Ruby standard library (as of 3.4.2, at least).
There’s just one problem with that thesis: The breakage seemingly happened between runs. I was even able to rerun one of the unit test builds on the same commit and confirmed that the rerun is broken.
Ok, but it’s definitely ActiveSupport, right?
Of course it’s ActiveSupport. Let me just check the logs.
Ok, so ActiveSupport is there… But… why two versions on the newer build?
Claude for an expedited attempt at explanation
what changed with .present? for activesupport 7.0.8.7 vs. activesupport 7.2.2.1
Based on the search results, I can see that there are version differences between ActiveSupport 7.0.8.7 and 7.2.2.1, but the search results don’t show specific changes to the .present? method itself. Let me search for the specific changelog entries.
Fetched rails/activesupport/CHANGELOG.md at v8.0.2 · rails/rails
github.com
Based on my search results, I can see that there were significant changes in ActiveSupport between version 7.0.8.7 and 7.2.2.1, but I don’t see any specific documented changes to the .present? method itself in the changelog entries I found.
In ActiveSupport 7.1+ (which 7.2.2.1 is based on), the gem changed to load only minimal dependencies by default
This means that methods like .present? and .blank? might not be automatically available unless you explicitly require the core extensions
What you might need to do: If you’re upgrading from 7.0.8.7 to 7.2.2.1 and suddenly .present? stops working, you may need to explicitly require:
ruby
require 'active_support/core_ext'
Or more specifically:
ruby
require 'active_support/core_ext/object/blank'
The functionality of .present? itself hasn’t changed – it still returns true for non-blank objects and false for blank ones. The change is primarily about how ActiveSupport loads these extensions.
This is a common issue that affected many projects when upgrading from ActiveSupport 7.0 to 7.1+, as the autoloading behavior became more conservative to reduce memory usage and improve performance.
Ok, so it’s ActiveSupport 7.1
So, ActiveSupport 7.1 is the culprit. I’d like to see the Release Notes on this
Are there release notes and a PR in which activesupport loads the minimum dependencies by default?
There was a long detailed response with 20+ references. The only direct mention that’s come up so far of the actual change? CocoaPods/CocoaPods issue #12089. I’m sure a detailed analysis of the activesupport code would show me, but the 7.1 release notes don’t seem to mention the change even indirectly.
Time to fix
My decision, was to substitute out pure Ruby code for the .present? call. This was based on the relatively high volatility of the Rails API (yes, pinning would help), the relative heaviness of activesupport, and this being the only usage of activesupport within a repo of 112k lines of (non-test) Ruby code. I took a naïve attempt at a replacement, but it broke for the scenarios of several types.
Claude’s suggestion:
But honestly, if you need .present? behavior, it’s much cleaner to either use ActiveSupport or implement the .present? method yourself rather than trying to replicate it with string manipulation.
I’m going to reject that for reasons above.
Of course, Claude needs more context
Is it actually worth including activesupport as a dependency for a codebase with 112k lines of non-test Ruby code if the only usage is a single .present? call?
(Am I leading the witness?) Now the response is more sensible.
No, it’s definitely not worth adding ActiveSupport as a dependency for a single .present? call in a 112k line codebase.
Here’s why:
The Cost
ActiveSupport is huge: It’s a substantial dependency with many features you won’t use
Bundle size: Adds significant weight to your application
Maintenance burden: Another dependency to keep updated and secure
Potential conflicts: Could introduce version conflicts with other gems
I decided to opt for a fairly verbose but dependency-free:
Claude quite a bit better at searching for the difference between specific ActiveSupport versions that my experience with GitHub and Google have been, particularly given that the actual mention of the change was found in a project using ActiveSupport
Treat suggestions as alternative perspectives, but assess them as coming from potentially naïve viewpoints.
If a solution or suggestion feels off, add the context that would make you disagree.
My best tools for troubleshooting this problem were deterministic: log output, grep, diff (with a preprocessing script that effectively scrubs the timestamps and unique identifiers to minimize noise). My most useful experiences with AI-assisted coding have been in building tools to get the busywork and tedious dumpster diving out of the way and to the business of solving the problem sooner.
Along the way I let GitHub Copilot write a little test script that compared solutions:
================================================================================
TEST SUMMARY
================================================================================
ActiveSupport 7.0.8.7:
✓ Basic require: success
Output: false
✗ Core extensions: failed
✓ Specific blank extension: success
Output: false
✓ All extensions: success
Output: false
ActiveSupport 7.2.2.1:
✗ Basic require: failed
✗ Core extensions: failed
✓ Specific blank extension: success
Output: false
✓ All extensions: success
Output: false
================================================================================
RECOMMENDATIONS
================================================================================
✓ Working combinations:
- 7.0.8.7 with Basic require
- 7.0.8.7 with Specific blank extension
- 7.0.8.7 with All extensions
- 7.2.2.1 with Specific blank extension
- 7.2.2.1 with All extensions