diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index d56b25214..ac9cee1dd 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -14,6 +14,10 @@ nav_order: 5 *Chris Nitsas* +* Introduce `yield :parent` as a replacement for `#render_parent`, which respects variants and deep inheritance hierarchies. + + *Cameron Dutro* + ## 3.4.0 * Avoid including Rails `url_helpers` into `Preview` class when they're not defined. diff --git a/docs/guide/templates.md b/docs/guide/templates.md index 35bcb08e4..6c1f9253d 100644 --- a/docs/guide/templates.md +++ b/docs/guide/templates.md @@ -129,7 +129,7 @@ To render a parent component's template from a subclass' template, use `yield :p ``` -If the parent supports the current variant, the variant will automatically be rendered. `yield :parent` replaces the deprecated `#render_parent` method, which does not respect variants or multiple levels of inheritance. +If the parent supports the current variant, the variant will automatically be rendered. `yield :parent` replaces the deprecated `#render_parent` method, which doesn't respect variants or multiple levels of inheritance. `yield :parent` also works with inline templates: @@ -154,7 +154,7 @@ class MyComponent < ViewComponent::Base end ``` -`super` will attempt to call the `#call_phone` method on the parent class. If the parent class does not support the "phone" variant, Ruby will raise a `NoMethodError`. Consider using a template and `render :parent` to handle superclass variants automatically. +`super` will attempt to call the `#call_phone` method on the parent class. If the parent class doesn't support the "phone" variant, Ruby will raise a `NoMethodError`. Consider using a template and `render :parent` to handle superclass variants automatically. ### render_parent diff --git a/lib/view_component/compiler.rb b/lib/view_component/compiler.rb index 2afe8f257..92592279c 100644 --- a/lib/view_component/compiler.rb +++ b/lib/view_component/compiler.rb @@ -96,6 +96,7 @@ def define_compiled_template_methods(method_name, template_info) component_class.silence_redefinition_of_method(method_name) component_class.silence_redefinition_of_method(unique_method_name) + # rubocop:disable Style/EvalWithLocation component_class.class_eval <<-RUBY, template_info[:path], template_info[:lineno] private def #{unique_method_name} if block_given? @@ -124,6 +125,7 @@ def #{method_name} #{unique_method_name} end RUBY + # rubocop:enable Style/EvalWithLocation end end diff --git a/test/sandbox/app/components/super_base_component.html.erb b/test/sandbox/app/components/super_base_component.html.erb new file mode 100644 index 000000000..95dc2504d --- /dev/null +++ b/test/sandbox/app/components/super_base_component.html.erb @@ -0,0 +1 @@ +
diff --git a/test/sandbox/app/components/super_base_component.rb b/test/sandbox/app/components/super_base_component.rb new file mode 100644 index 000000000..62ab304c3 --- /dev/null +++ b/test/sandbox/app/components/super_base_component.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +class SuperBaseComponent < ViewComponent::Base +end diff --git a/test/sandbox/app/components/super_component.html.erb b/test/sandbox/app/components/super_component.html.erb new file mode 100644 index 000000000..b40543223 --- /dev/null +++ b/test/sandbox/app/components/super_component.html.erb @@ -0,0 +1,3 @@ +
+ <%= render_parent %> +
diff --git a/test/sandbox/app/components/super_component.rb b/test/sandbox/app/components/super_component.rb new file mode 100644 index 000000000..e92084a17 --- /dev/null +++ b/test/sandbox/app/components/super_component.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +class SuperComponent < SuperBaseComponent +end diff --git a/test/sandbox/test/rendering_test.rb b/test/sandbox/test/rendering_test.rb index 96bdb5b02..bff3ce522 100644 --- a/test/sandbox/test/rendering_test.rb +++ b/test/sandbox/test/rendering_test.rb @@ -960,6 +960,15 @@ def test_inherited_component_renders_when_lazy_loading assert_selector("div", text: "hello, my own template") end + def test_render_parent + render_inline(SuperComponent.new) + + assert_selector(".base-component", count: 1) + assert_selector(".derived-component", count: 1) do |derived| + derived.assert_selector(".base-component", count: 1) + end + end + def test_child_components_can_render_parent render_inline(Level3Component.new)