From fb9b079c7c0f121a3703471ddb68f8b054840917 Mon Sep 17 00:00:00 2001 From: reeganviljoen Date: Wed, 19 Mar 2025 09:52:41 +0200 Subject: [PATCH 1/3] poc --- docs/CHANGELOG.md | 2 +- lib/view_component/engine.rb | 10 ++++++++++ .../render_layout_monkey_patch.rb | 20 +++++++++++++++++++ .../app/components/layout_component.html.erb | 3 +++ .../app/components/layout_component.rb | 5 +++++ test/sandbox/test/rendering_test.rb | 7 +++++++ 6 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 lib/view_component/render_layout_monkey_patch.rb create mode 100644 test/sandbox/app/components/layout_component.html.erb create mode 100644 test/sandbox/app/components/layout_component.rb diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 63a2ede33..7d0d760a4 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,4 +1,4 @@ ---- +lear --- layout: default title: Changelog nav_order: 5 diff --git a/lib/view_component/engine.rb b/lib/view_component/engine.rb index b920eb5d8..3ed144622 100644 --- a/lib/view_component/engine.rb +++ b/lib/view_component/engine.rb @@ -111,6 +111,16 @@ class Engine < Rails::Engine # :nodoc: # :nocov: end + initializer "view_component.monkey_patch_render_collection" do |app| + next if Rails.version.to_f <= 6.1 + + ActiveSupport.on_load(:action_view) do + require "view_component/render_layout_monkey_patch.rb" + ActionView::Base.prepend ViewComponent::RenderLayoutMonkeyPatch + end + # :nocov: + end + initializer "view_component.include_render_component" do |_app| next if Rails.version.to_f >= 6.1 diff --git a/lib/view_component/render_layout_monkey_patch.rb b/lib/view_component/render_layout_monkey_patch.rb new file mode 100644 index 000000000..e73b220ad --- /dev/null +++ b/lib/view_component/render_layout_monkey_patch.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module ViewComponent + module RenderLayoutMonkeyPatch # :nodoc: + def render(options = {}, locals = {}, &block) + if locals[:layout].blank? || locals[:layout].is_a?(Symbol) || locals[:layout].is_a?(String) + super(options, locals, &block) + else + render(locals[:layout]) do + options.render_in(self, &block) + end + end + end + end +end + + + + + diff --git a/test/sandbox/app/components/layout_component.html.erb b/test/sandbox/app/components/layout_component.html.erb new file mode 100644 index 000000000..9aaf397c1 --- /dev/null +++ b/test/sandbox/app/components/layout_component.html.erb @@ -0,0 +1,3 @@ +
+ <%= content %> +
\ No newline at end of file diff --git a/test/sandbox/app/components/layout_component.rb b/test/sandbox/app/components/layout_component.rb new file mode 100644 index 000000000..4443989b7 --- /dev/null +++ b/test/sandbox/app/components/layout_component.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +class LayoutComponent < ViewComponent::Base + +end diff --git a/test/sandbox/test/rendering_test.rb b/test/sandbox/test/rendering_test.rb index 356b0d7db..6fa567f98 100644 --- a/test/sandbox/test/rendering_test.rb +++ b/test/sandbox/test/rendering_test.rb @@ -1255,4 +1255,11 @@ def test_render_anonymous_component_without_template render_inline(mock_component.new) end end + + def test_layout_attribute + render_inline(MyComponent.new, layout: LayoutComponent.new) + + assert_selector("div", text: "hello,world!") + assert_selector(".layout__container") + end end From 207f0e1c1553a7a9ec7678235916438e3faa895b Mon Sep 17 00:00:00 2001 From: reeganviljoen Date: Wed, 19 Mar 2025 17:11:28 +0200 Subject: [PATCH 2/3] add layout poc --- lib/view_component/engine.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/view_component/engine.rb b/lib/view_component/engine.rb index 3ed144622..17e084084 100644 --- a/lib/view_component/engine.rb +++ b/lib/view_component/engine.rb @@ -111,7 +111,7 @@ class Engine < Rails::Engine # :nodoc: # :nocov: end - initializer "view_component.monkey_patch_render_collection" do |app| + initializer "view_component.monkey_patch_render_layout" do |app| next if Rails.version.to_f <= 6.1 ActiveSupport.on_load(:action_view) do From 69f34d3fc2c44bf938905723a12cfe28ec1a368e Mon Sep 17 00:00:00 2001 From: reeganviljoen Date: Wed, 19 Mar 2025 17:11:39 +0200 Subject: [PATCH 3/3] add layout poc --- .github/workflows/ci.yml | 6 ++++++ lib/view_component/config.rb | 7 +++++++ lib/view_component/engine.rb | 3 ++- test/sandbox/config/environments/test.rb | 1 + test/sandbox/test/rendering_test.rb | 8 +++++--- 5 files changed, 21 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 66f1eb4f5..336ccb3f7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,6 +71,11 @@ jobs: - ruby_version: "head" rails_version: "main" mode: "capture_patch_enabled" + - ruby_version: "head" + rails_version: "main" + mode: "capture_patch_enabled" + layout_patch: "true" + env: BUNDLE_GEMFILE: gemfiles/rails_${{ matrix.rails_version }}.gemfile steps: @@ -92,6 +97,7 @@ jobs: RAILS_VERSION: ${{ matrix.rails_version }} RUBY_VERSION: ${{ matrix.ruby_version }} CAPTURE_PATCH_ENABLED: ${{ matrix.mode == 'capture_patch_enabled' && 'true' || 'false' }} + RENDER_LAYOUT_PATCH_ENABLED: ${{ matrix.layout_patch == 'true' || 'false' }} - name: Upload coverage results uses: actions/upload-artifact@v4.4.0 if: always() diff --git a/lib/view_component/config.rb b/lib/view_component/config.rb index 3edcd22d2..362dc9f8d 100644 --- a/lib/view_component/config.rb +++ b/lib/view_component/config.rb @@ -19,6 +19,7 @@ def defaults instrumentation_enabled: false, use_deprecated_instrumentation_name: true, render_monkey_patch_enabled: true, + render_layout_monkey_patch_enabled: false, view_component_path: "app/components", component_parent_class: nil, show_previews: Rails.env.development? || Rails.env.test?, @@ -132,6 +133,12 @@ def defaults # `#render_component_to_string` instead. # Defaults to `true`. + # @!attribute render_layout_monkey_patch_enabled + # @return [Boolean] Whether the #render method should be monkey patched. + # If this is disabled, use `#render_component` or + # `#render_component_to_string` instead. + # Defaults to `true`. + # @!attribute view_component_path # @return [String] # The path in which components, their templates, and their sidecars should diff --git a/lib/view_component/engine.rb b/lib/view_component/engine.rb index 17e084084..a29aa9bcb 100644 --- a/lib/view_component/engine.rb +++ b/lib/view_component/engine.rb @@ -34,6 +34,7 @@ class Engine < Rails::Engine # :nodoc: end options.instrumentation_enabled = false if options.instrumentation_enabled.nil? options.render_monkey_patch_enabled = true if options.render_monkey_patch_enabled.nil? + options.render_layout_monkey_patch_enabled = false if options.render_layout_monkey_patch_enabled.nil? options.show_previews = (Rails.env.development? || Rails.env.test?) if options.show_previews.nil? if options.show_previews @@ -112,7 +113,7 @@ class Engine < Rails::Engine # :nodoc: end initializer "view_component.monkey_patch_render_layout" do |app| - next if Rails.version.to_f <= 6.1 + next if Rails.version.to_f <= 6.1 || !app.config.view_component.render_layout_monkey_patch_enabled ActiveSupport.on_load(:action_view) do require "view_component/render_layout_monkey_patch.rb" diff --git a/test/sandbox/config/environments/test.rb b/test/sandbox/config/environments/test.rb index 8896f7e96..12a932251 100644 --- a/test/sandbox/config/environments/test.rb +++ b/test/sandbox/config/environments/test.rb @@ -34,6 +34,7 @@ config.view_component.preview_paths << "#{Rails.root}/lib/component_previews" config.view_component.render_monkey_patch_enabled = true + config.view_component.render_layout_monkey_patch_enabled = ENV["RENDER_LAYOUT_PATCH_ENABLED"] == "true" config.view_component.show_previews_source = true config.view_component.test_controller = "IntegrationExamplesController" config.view_component.capture_compatibility_patch_enabled = ENV["CAPTURE_PATCH_ENABLED"] == "true" diff --git a/test/sandbox/test/rendering_test.rb b/test/sandbox/test/rendering_test.rb index 6fa567f98..b87148341 100644 --- a/test/sandbox/test/rendering_test.rb +++ b/test/sandbox/test/rendering_test.rb @@ -1257,9 +1257,11 @@ def test_render_anonymous_component_without_template end def test_layout_attribute - render_inline(MyComponent.new, layout: LayoutComponent.new) + if Rails.version.to_f >= 6.1 && ViewComponent::Base.config.render_layout_monkey_patch_enabled + render_inline(MyComponent.new, layout: LayoutComponent.new) - assert_selector("div", text: "hello,world!") - assert_selector(".layout__container") + assert_selector("div", text: "hello,world!") + assert_selector(".layout__container") + end end end