From e09c2a587a281a8012dc119c087861d61985a5ae Mon Sep 17 00:00:00 2001 From: Justin Coyne Date: Fri, 31 Jul 2026 08:41:15 -0500 Subject: [PATCH 1/5] Add a failing test for rendering a partial inside a collection rendering --- Gemfile.lock | 2 +- test/sandbox/test/collection_test.rb | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 6f2565291..cf2e08ec6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - view_component (3.24.0) + view_component (3.25.0) activesupport (>= 5.2.0, < 8.2) concurrent-ruby (~> 1) method_source (~> 1.0) diff --git a/test/sandbox/test/collection_test.rb b/test/sandbox/test/collection_test.rb index 7d1b56d1c..01ab43f48 100644 --- a/test/sandbox/test/collection_test.rb +++ b/test/sandbox/test/collection_test.rb @@ -22,6 +22,20 @@ def call end end + # Renders a plain partial, which routes through `ViewComponent::Base#render` + # and so depends on `__vc_original_view_context` being set. + class PartialRenderingComponent < ViewComponent::Base + with_collection_parameter :item + + def initialize(item: nil) + @item = item + end + + def call + render partial: "integration_examples/test_partial" + end + end + def setup @products = [Product.new(name: "Radio clock"), Product.new(name: "Mints")] @collection = ProductComponent.with_collection(@products, notice: "secondhand") @@ -46,5 +60,15 @@ def test_supports_collection_with_spacer_component render_inline(ProductComponent.with_collection(@products, spacer_component: SpacerComponent.new)) assert_selector("hr", count: 1) end + + # A collection rendered from a plain view (rather than from inside another + # component) never has `set_original_view_context` called on it, so its own + # `__vc_original_view_context` is nil. That nil must not be forwarded to the + # child components, or rendering a partial from one raises NoMethodError. + def test_supports_components_that_render_partials + render_inline(PartialRenderingComponent.with_collection([1, 2])) + + assert_text("hello,partial world!", count: 2) + end end end From 292d09f3de343f8b796eca27129ad36002076c10 Mon Sep 17 00:00:00 2001 From: Joel Hawksley Date: Wed, 12 Aug 2026 14:13:21 -0600 Subject: [PATCH 2/5] Fix original view context fallback for collections --- lib/view_component/base.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/view_component/base.rb b/lib/view_component/base.rb index d7e98ab94..a5e6626b4 100644 --- a/lib/view_component/base.rb +++ b/lib/view_component/base.rb @@ -88,7 +88,7 @@ def render_in(view_context, **options, &block) @view_context = view_context self.__vc_original_view_context = if instance_variable_defined?(:@__vc_pending_original_view_context) - remove_instance_variable(:@__vc_pending_original_view_context) + remove_instance_variable(:@__vc_pending_original_view_context) || view_context else view_context end From c2f944ace97d84d7704244f4934f6763fc33835a Mon Sep 17 00:00:00 2001 From: Joel Hawksley Date: Wed, 12 Aug 2026 14:17:28 -0600 Subject: [PATCH 3/5] Add changelog entry for collection partial fix --- docs/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 7f898ee77..306408de5 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -10,6 +10,10 @@ nav_order: 6 ## main +* Fix rendering partials from components rendered as a collection when the original view context is explicitly stashed as `nil`. + + *Justin Coyne, Joel Hawksley* + ## 3.25.0 * Support Rails `render_in` options signature. Rails [#50623](https://github.com/rails/rails/pull/50623) changed the `render_in` signature from `render_in(view_context, &block)` to `render_in(view_context, **options, &block)`. `ViewComponent::Base#render_in`, `ViewComponent::Collection#render_in`, and `ViewComponent::Instrumentation#render_in` now accept `**options`, restoring compatibility with Rails main and silencing the deprecation warning. From f11ef8a59cad0841408a11ef84bee5551b6b1a9e Mon Sep 17 00:00:00 2001 From: Joel Hawksley Date: Wed, 12 Aug 2026 14:23:20 -0600 Subject: [PATCH 4/5] Restore Rails main template handler compatibility --- docs/CHANGELOG.md | 4 ++++ lib/view_component/compiler.rb | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 306408de5..02f2fdf98 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -14,6 +14,10 @@ nav_order: 6 *Justin Coyne, Joel Hawksley* +* Restore compatibility with Rails main after `ActionView::Template.template_handler_extensions` was removed. + + *Joel Hawksley* + ## 3.25.0 * Support Rails `render_in` options signature. Rails [#50623](https://github.com/rails/rails/pull/50623) changed the `render_in` signature from `render_in(view_context, &block)` to `render_in(view_context, **options, &block)`. `ViewComponent::Base#render_in`, `ViewComponent::Collection#render_in`, and `ViewComponent::Instrumentation#render_in` now accept `**options`, restoring compatibility with Rails main and silencing the deprecation warning. diff --git a/lib/view_component/compiler.rb b/lib/view_component/compiler.rb index c4ab88df4..ae5ba61c0 100644 --- a/lib/view_component/compiler.rb +++ b/lib/view_component/compiler.rb @@ -170,7 +170,7 @@ def gather_templates @templates ||= begin templates = @component.sidecar_files( - ActionView::Template.template_handler_extensions + template_handler_extensions ).map do |path| # Extract format and variant from template filename this_format, variant = @@ -225,5 +225,13 @@ def gather_templates templates end end + + def template_handler_extensions + if ActionView::Template.respond_to?(:template_handler_extensions) + ActionView::Template.template_handler_extensions + else + ActionView::Template::Handlers.extensions.map(&:to_s) + end + end end end From d73a91ea93507b86c37b166dba59c148599321fe Mon Sep 17 00:00:00 2001 From: Joel Hawksley Date: Wed, 12 Aug 2026 14:30:27 -0600 Subject: [PATCH 5/5] Restore Rails main preview source lookup compatibility --- app/helpers/preview_helper.rb | 10 +++++++++- docs/CHANGELOG.md | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/app/helpers/preview_helper.rb b/app/helpers/preview_helper.rb index bac7557bc..db8d1637a 100644 --- a/app/helpers/preview_helper.rb +++ b/app/helpers/preview_helper.rb @@ -23,7 +23,7 @@ def prism_js_source_url end def find_template_data_for_preview_source(lookup_context:, template_identifier:) - template = lookup_context.find_template(template_identifier) + template = find_template_for_preview_source(lookup_context, template_identifier) if Rails.version.to_f >= 6.1 || template.source.present? { @@ -61,6 +61,14 @@ def find_template_data_for_preview_source(lookup_context:, template_identifier:) private + def find_template_for_preview_source(lookup_context, template_identifier) + if lookup_context.respond_to?(:find_template) + lookup_context.find_template(template_identifier) + else + lookup_context.find(template_identifier) + end + end + def prism_language_name_by_template(template:) language = template.identifier.split(".").last diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 02f2fdf98..61fe6a9a8 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -14,7 +14,7 @@ nav_order: 6 *Justin Coyne, Joel Hawksley* -* Restore compatibility with Rails main after `ActionView::Template.template_handler_extensions` was removed. +* Restore compatibility with Rails main after `ActionView::Template.template_handler_extensions` and `ActionView::LookupContext#find_template` were removed. *Joel Hawksley*