-
Notifications
You must be signed in to change notification settings - Fork 443
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
Request formats addition breaks variants lookup #2128
Comments
I don't understand why this feature looks at the request rather than the response. For example, here's the lookup context for this situation:
Wouldn't it make more sense to look at the formats defined in the |
I've encountered the same issue. Upgrading to version 3.15 or higher breaks our Hotwire Native mobile apps. |
@sfnelson That generally sounds right to me, would you like to take a crack at writing a fix? 2128-variant has a failing test 😄 While we've done the best we can to try to test all Rails rendering paths, I continue to be amazed at all of the cases we have to handle to be compatible 😂 |
@joelhawksley I've had a look at how Rails handles this logic, and the key code path to understand is My superficial understanding of this code path is that the view context is used to construct an instance of Given your understanding of the goals of the ViewComponents project, would it be better to try and re-use ActionView's logic or re-implement something simpler and give up some compatibility? I think that aiming for compatibility with the full complexity of ActionView would result in a fairly significant change to the approach currently used by ViewComponent ( |
To give you an idea of what this could look like, side-stepping compilation and short circuit optimisations, here's an implementation that uses Rails' ordering logic:
Is this strategy worth pursuing further? A key difference between this strategy and the current ViewComponent logic is that the ordering can vary based on the request – i.e. the priority ordering of templates can be different based on the lookup context. Because of this, I don't think there would be any benefit from pre-compiling the switch logic. |
@sfnelson wow! Thank you for digging into the Rails side to see how it compares to the ViewComponent implementation. My two main concerns with going this direction are 1) using private APIs and 2) performance. Regarding #1, I'd want to work with Rails Core to make that API public before we can use it. In general, if we can address those two concerns, I'm amenable to heading in this direction to better align with Rails. I can imagine there are many more edge case bugs waiting to be found in this space due to our current implementation being completely different from Rails'. |
@joelhawksley that all makes sense. Do you have a benchmark suite for testing performance changes? I've got a background in compilers, I'd be happy to assist further. Re (2) my instincts are that there isn't a significant difference between the old and new changes for the majority of users as the priority ordering is only relevant to users who are using multiple templates for the same component. Given that these issues haven't come up before I suspect this is a fringe group of users, but hard to tell without a better understanding of how the community uses the gem, which I suspect would be hard to quantify. Re (1) I also had reservations, but this was the most pragmatic solution to get some code in front of you. I doubt that this is a feature that the Rails core team would be interested in exposing as it really does seem like implementation detail. There are other options however, just nothing that was appropriate for a spike like this:
There are several benefits to ViewComponents to adopting the Rails approach:
I think this could be a great feature for v4. |
@sfnelson thank you for your interest in helping out here! ❤ This is a great time to be looking into something that might be a breaking change as we set the path for v4: #2085. Yes, we do have a benchmark suite in the repo: https://github.com/ViewComponent/view_component/blob/main/Rakefile You're right to point out that these cases are very fringe. ViewComponent has been widely adopted since 2019 and it's telling that we've not seen this issue arise for very many folks when we made the request format change. I could see the Rails core team going either way. They are keen to enable us to build our framework, and I'm guessing the resolver logic is pretty stable. I think the path to staying in sync with Rails would be best. Perhaps we verify that using Resolver will not regress on performance, then look into making it a public API? Otherwise, I think we port the logic. FWIW, we do already have locale-specific templates. |
@joelhawksley that sounds like a good approach to me as an approach. I've run the benchmarks and the performance seems comparable – there's more variation from run to run that there is from this change, any effect is lost in the noise. Having read more of the source, I've had some time today to look at code approaches and I think I can prepare a PR without requiring immediate input from the Rails team by using Ruby refinements. This allows ViewComponents to access the internal I've found a few problems in this code exploration that I think are worth documenting separately. I'll create separate issues and link to this one. |
See discussion about dropping support for Rails does not support variant names containing |
Steps to reproduce
custom
.Expected behavior
The custom variant should be rendered.
Actual behavior
The default variant is rendered
System configuration
Rails version:
7.2.1
Ruby version:
3.3.5
Gem version:
3.17.0
Context
Prior to 3.15 adding request formats, this worked as expected because the request type was not considered. With 3.15 the addition of request formats it's now impossible to fall back to a default response type (i.e. html when the response is a turbo stream) without losing the variant. This is a problem because it means variants cannot be used for both html and turbo streams after this change.
This is the generated
render_template_for
method:When
render_template_for
is called, the format is:turbo_stream
and the variant is:custom
, but because the format doesn't match the variant is never considered. I'm not sure what the intended behaviour of this code is, but it seems at odds with the way that Rails view templates behave (i.e. choosing the appropriate response type based on the accepts header).Example controller method:
Example view partial
new.turbo_stream.erb
:The text was updated successfully, but these errors were encountered: