Skip to content

Conversation

@kyleburgess2025
Copy link
Contributor

@kyleburgess2025 kyleburgess2025 commented Dec 11, 2025

Prior to this change, the validation for numericality was skipped if allow_blank was set to true and a string was provided. This happened because typecasting the string resulted in nil, which caused the validation check to be bypassed here. We have updated read_attribute_for_validation to return the original, non-typecasted value if typecasting to a numeric type fails.

@kyleburgess2025 kyleburgess2025 marked this pull request as ready for review December 11, 2025 21:45
@kyleburgess2025 kyleburgess2025 requested a review from a team as a code owner December 11, 2025 21:45
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses MONGOID-5842 by fixing validation behavior when validates_numericality_of is used with allow_blank: true and a non-numeric string is assigned to a numeric field. The fix ensures that non-numeric strings are properly validated as invalid, rather than being coerced to nil/0 before validation.

Key Changes

  • Modified read_attribute_for_validation to return the pre-type-cast value for BigDecimal, Float, and Integer fields
  • Added comprehensive test coverage for allow_blank: true scenarios with both Integer and Float field types

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
lib/mongoid/validatable.rb Added logic to return pre-type-cast values for numeric field types during validation
spec/mongoid/validatable/numericality_spec.rb Added test cases for allow_blank: true validation behavior with Integer and Float fields

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Contributor

@jamis jamis left a comment

Choose a reason for hiding this comment

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

Very nice. Thank you for your work on this!

I know I suggested this solution, but I was thinking more about it this morning and I worry a bit about changing read_attribute_for_validation like this. It's a Rails API, not a Mongoid one, which means we don't have any control over how Rails decides to use it. A new version of Rails could easily call that method somewhere unexpected, and expect a numeric value to be returned for a numeric field. The default implementation of prepare_value_for_validation, for example, simply returns the value it is given.

At the core of the issue, and this incompatibility, is the fact that ActiveRecord returns 0, not nil, when a non-numeric value is set and allow_blank is true. It's also how Ruby itself works (e.g. "hello".to_i # => 0). I wonder if we ought to roll that change back, so that Mongoid mirrors this? The alternative is probably to subclass NumericalValidator and write our own #validate method, to accommodate the fact that Mongoid returns nil instead of 0, here.

We should discuss this as a team next week, but this is a very good example of what we're trying to do with the Mongoid X initiative: this used to work, and now it doesn't. Do we revert the change? Do we allow the change and find a way to work around it? Or do we say that the new way is correct and the old way is wrong, and we describe how people ought to update their apps to accommodate that?

So. Let's hold off on further work here until we know what we want to do. Thank you for your investigation on this!

@johnnyshields
Copy link
Contributor

johnnyshields commented Dec 13, 2025

At the core of the issue, and this incompatibility, is the fact that ActiveRecord returns 0, not nil, when a non-numeric value is set and allow_blank is true. It's also how Ruby itself works (e.g. "hello".to_i # => 0). I wonder if we ought to roll that change back, so that Mongoid mirrors this?

I strongly, strongly vote against changing this. nil is the correct behavior here; 0 is a valid number, the same as any other number. Coercing a string like "Foobar" to a number should not return any valid number, 0 or otherwise.

@kyleburgess2025 kyleburgess2025 added the bug Fixes a bug, with no new features or broken compatibility label Dec 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Fixes a bug, with no new features or broken compatibility

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants