Avoid double cast in types that only override cast #46219
Merged
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.
Follow-up to #44625.
In #44625, the
SerializeCastValue
module was added to allow types to avoid a redundant call tocast
when serializing a value for the database. Because it introduced a new method (serialize_cast_value
) that was not part of theActiveModel::Type::Value
contract, it was designed to be opt-in. Furthermore, to guard against incompatibleserialize
andserialize_cast_value
implementations in types that overrideserialize
but (unintentionally) inheritserialize_cast_value
, types were required to explicitly include theSerializeCastValue
module to activate the optimization. i.e. It was not sufficient just to haveSerializeCastValue
in the ancestor chain.The
SerializeCastValue
module is not part of the public API, and there are no plans to change that, which meant user-created custom types could not benefit from this optimization.This commit changes the opt-in condition such that it is sufficient for the owner of the
serialize_cast_value
method to be the same or below the owner of theserialize
method in the ancestor chain. This means a user-created type that only overridescast
, notserialize
, will now benefit from the optimization. For example, a type like:As demonstrated in the benchmark below, this commit does not change the current performance of the built-in Active Model types. However, for a simple custom type like
DowncasedString
, the performance ofvalue_for_database
is twice as fast. For types with more expensivecast
operations, the improvement may be greater.Benchmark script
Before
After