Skip to content

Stop relying on the private validation_context= writer - #770

Open
hikmetba-bit wants to merge 1 commit into
stefankroes:masterfrom
hikmetba-bit:fix/validation-context-writer-removed-766
Open

hikmetba-bit wants to merge 1 commit into
stefankroes:masterfrom
hikmetba-bit:fix/validation-context-writer-removed-766

Conversation

@hikmetba-bit

Copy link
Copy Markdown

Summary

Fixes #766.

sane_ancestor_ids? saved, nulled, and restored self.validation_context around a direct call to each column validator's #validate_each. Rails main removed the private validation_context= writer entirely (rails/rails#58220), since ActiveModel::Validations#valid? now sets the context on an internal ValidationContext object instead. The removed writer breaks sane_ancestor_ids? on current Rails main with:

NoMethodError: undefined method 'validation_context=' for an instance of Node

which in turn breaks moving a node that has descendants and check_ancestry_integrity! (both call this method), exactly as described in the issue (credit to the reporter for the excellent diagnosis, down to the exact Rails PR and line number).

Fix

This is Option 1 from the issue: the save/restore was unnecessary to begin with. validate_each is called directly on each validator here, bypassing the normal valid?/run_validations! pipeline that actually reads validation_context — so nulling and restoring it around this direct call never affected which validators ran or how. Dropped both the write and the ensure restore.

Test

Added test_sane_ancestor_ids_does_not_rely_on_validation_context_writer to integrity_checking_and_restoration_test.rb: it stubs validation_context= on a single instance to raise NoMethodError (simulating the writer's removal on Rails main) and confirms sane_ancestor_ids? still runs to completion. Mutation-tested: reverting the source change makes it fail with that exact NoMethodError through sane_ancestor_ids?; with the fix, the full integrity_checking_and_restoration_test.rb file passes (4/4). Ran the full suite (SKIP_NATIVE_DB_GEMS=1 bundle exec rake test — trilogy/pg require native client libs not available in this sandbox, so I tested against the default SQLite adapter only): 259 runs, same 5 pre-existing SortByAncestryTest failures with or without this change (confirmed by reverting and re-running - those failures are SQLite ordering-related and unrelated to this fix), no new failures.

🤖 Generated with Claude Code

sane_ancestor_ids? saved/nulled/restored self.validation_context
around a direct call to each column validator's #validate_each. Rails
main removed the private validation_context= writer entirely
(rails/rails#58220) since ActiveModel::Validations#valid? now sets the
context on an internal ValidationContext object instead, so this call
raises NoMethodError on current Rails main, breaking any move of a
node with descendants and check_ancestry_integrity!.

The save/restore was unnecessary in the first place: validate_each is
called directly here, bypassing the normal valid?/run_validations!
pipeline that consults validation_context, so nulling and restoring it
around the call had no effect on which validators ran. Drop it.

Fixes stefankroes#766.
@kbrock

kbrock commented Sep 20, 2026

Copy link
Copy Markdown
Collaborator

@hikmetba-bit so we are using this to detect if we introduced an error or if there was an error from the model. (some people save records to the database with errors in them - which happens when you modify your validations and don't revalidate every record in the database)

So this concept is necessary in general Maybe there is a better way for us to validate that we properly updated the ancestry with a custom validator or calling the validator directly?
I was trying to get away from custom logic and go towards leveraging the validators that are already setup.

Need to look into how rails suggests running a subset of validators. I think this concept is still necessary to rails in general, so it may be as simple as tracking down how this changed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

NoMethodError: undefined method 'validation_context=' on Rails main (removed in rails/rails#58220)

2 participants