New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Avoid calling to_s at end of ERB #45756
Conversation
With the recent changes to OutputBuffer, calling `to_s` is extremely expensive if the buffer later is concatenated to (if the buffer never changes it should be relatively inexpensive, as Ruby will share memory).
6f72df1
to
ee68644
Compare
🤦 I definitely didn't think of shared string while writing this. I'm definitely good with returning the buffer itself, rendering partials directly into the parent buffer is one of the things I'm trying to achieve with these refactors, so 👍 . Until we get there though, we might need to make sure |
But I'm good with merging this as is 👍 |
I think that should be fine as |
Rails 7.1 has sped up its internal OutputBuffer implementation (what handles << concatenation in templates), which we rely on tricking a bit. rails/rails#45614 Then a follow up PR the `to_s` call was moved to after calling `view._run` rails/rails#45756 However, we rely on the return value being a Hash (which I'm not sure how to fix yet). So since `target!` is the return value of our templates, we can wrap that and ensure `to_s` doesn't actually `to_s`, which Rails 7.1 will call for us. On Rails < 7.1 we must call the compatibility `unwrap_target!` method ourselves to get our inner Hash return value. This also adds a Rails version matrix so we can detect these things before release in the future.
* Fix Rails 7.1 compatibility. Rails 7.1 has sped up its internal OutputBuffer implementation (what handles << concatenation in templates), which we rely on tricking a bit. rails/rails#45614 Then a follow up PR the `to_s` call was moved to after calling `view._run` rails/rails#45756 However, we rely on the return value being a Hash (which I'm not sure how to fix yet). So since `target!` is the return value of our templates, we can wrap that and ensure `to_s` doesn't actually `to_s`, which Rails 7.1 will call for us. On Rails < 7.1 we must call the compatibility `unwrap_target!` method ourselves to get our inner Hash return value. This also adds a Rails version matrix so we can detect these things before release in the future. * Allow us to run tests in multiple Rails versions * Yep, I'm calling it, don't think it's worth it anymore * Fix enum invocation for Rails 6.1 tests
With the recent changes to OutputBuffer, calling
to_s
is extremely expensive if the buffer later is concatenated to (if the buffer never changes it should be relatively inexpensive, as Ruby will share memory).This tries to avoid calling
to_s
where possible, and to explicitly return nil when a buffer is passed totemplate.render
Before
After