Fix nil-comparison issues: bracket access and cache invalidation - #7
Open
gillisd wants to merge 2 commits into
Open
Fix nil-comparison issues: bracket access and cache invalidation#7gillisd wants to merge 2 commits into
gillisd wants to merge 2 commits into
Conversation
Note that these specs should be put in the appropriate places, this is just a temp location so that they aren't lost
Owner
Author
Code reviewNo issues found. Checked for bugs and CLAUDE.md compliance. 🤖 Generated with Claude Code - If this code review was useful, please react with 👍. Otherwise, react with 👎. |
gillisd
added a commit
that referenced
this pull request
Apr 29, 2026
Pattern matching via case/in now mirrors Core#[] — phantom keys created by a method-touch bind to literal nil instead of leaking the empty Flexor. Extends the bracket-nil contract from PR #7 across the pattern-matching surface in both Core and FlexKeys. Note: deconstruct_keys now diverges from to_h on phantom keys (included-as-nil vs omitted), pinned in flexor_conversion_spec so the trade-off stays discoverable.
gillisd
force-pushed
the
fix/nil-comparison-issues
branch
from
June 22, 2026 16:47
1ad462a to
7989107
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Flexor#[]now returns Ruby's literalnilfor missing keys AND for empty Flexors already in storage, so||=,||, and conditional assignment behave the way Ruby developers expect. Phantom Flexors no longer leak into truthiness checks.f.foo) keeps autovivifying — the documented "Safe Chaining" feature (f.user.name = "Joe") is preserved end-to-end, including when interleaved with bracket access.#deleteor#clear, cached singleton getters from prior method access are now invalidated, so re-accessing a removed key vivifies a fresh child Flexor instead of returning a stalenil.FlexKeysinvalidates the case counterpart as well, so deleting:user_namealso clears any cached:userNamegetter.docs/specification.yaml. Cached method getters resolve through FlexKeys correctly (camelCase ↔ snake_case still round-trips on the second call).Test plan
bundle exec rakeis fully green (377 examples, 0 failures; rubocop 0 offenses)f = Flexor.new; f[:foo] ||= :bar; f[:foo]→:bar_ = f.foo; f[:foo] ||= :bar; f[:foo]→:barf = Flexor.new; f.user.name = "Joe"; f[:user][:name]→"Joe"s = Flexor.new(fooBar: "v"); s.foo_bar; s.foo_bar→"v"on both callsf = Flexor.new(user: { name: "a" }); f.user.name; f.delete(:user); f.user.name = "b"returns"b"(noNoMethodErroron nil)f.clearsubstituted forf.delete(:user)s = Flexor.new(user_name: { nickname: "a" }); s.userName.nickname; s.delete(:user_name); s.userName.nickname = "b"returns"b"Flexor.new[:user][:name] = "x"raisesNoMethodError(use method-style chain instead)FrozenErrorNotes
Closes issue
3ED3C15C-4051-11F1-9F71-FE6CB9572C2Finissues.rec.Trade-off accepted: bracket-chain assignment through an unset intermediate (
f[:user][:name] = "x"when:useris unset) now raisesNoMethodError. Usef.user[:name] = "x"orf.user.name = "x"instead. README and contract specs document this explicitly.