From b3bb06a24a21fda9fa9a0e4409ffeff123f6b464 Mon Sep 17 00:00:00 2001 From: Sean Doyle Date: Mon, 8 Jan 2024 23:40:11 -0500 Subject: [PATCH] Raise `ArgumentError` if `:renderable` object does not respond to `#render_in` When calling `render` with a `:renderable` argument, ensure that the object responds to `#render_in`. If it doesn't, raise an `ArgumentError`. This commit also adjusts the `ArgumentError` that when a `:partial` argument isn't Active Model compatible. Prior to this commit, the message used `:` as a prefix to `to_partial_path`. This commit replaces that with a `#` prefix to denote that it's expected to be an instance method on the object. --- actionview/CHANGELOG.md | 4 ++++ .../action_view/renderer/abstract_renderer.rb | 2 +- .../lib/action_view/template/renderable.rb | 2 ++ actionview/test/template/render_test.rb | 19 +++++++++++++++++-- 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md index 668bbc48021..b79172de4ee 100644 --- a/actionview/CHANGELOG.md +++ b/actionview/CHANGELOG.md @@ -1,3 +1,7 @@ +* Raise `ArgumentError` if `:renderable` object does not respond to `#render_in` + + *Sean Doyle* + * Add the `nonce: true` option for `stylesheet_link_tag` helper to support automatic nonce generation for Content Security Policy. Works the same way as `javascript_include_tag nonce: true` does. diff --git a/actionview/lib/action_view/renderer/abstract_renderer.rb b/actionview/lib/action_view/renderer/abstract_renderer.rb index 844cf49b011..e5702654e1b 100644 --- a/actionview/lib/action_view/renderer/abstract_renderer.rb +++ b/actionview/lib/action_view/renderer/abstract_renderer.rb @@ -79,7 +79,7 @@ module ActionView path = if object.respond_to?(:to_partial_path) object.to_partial_path else - raise ArgumentError.new("'#{object.inspect}' is not an ActiveModel-compatible object. It must implement :to_partial_path.") + raise ArgumentError.new("'#{object.inspect}' is not an ActiveModel-compatible object. It must implement #to_partial_path.") end if view.prefix_partial_path_with_controller_namespace diff --git a/actionview/lib/action_view/template/renderable.rb b/actionview/lib/action_view/template/renderable.rb index c37bd1cb5e2..53175416a95 100644 --- a/actionview/lib/action_view/template/renderable.rb +++ b/actionview/lib/action_view/template/renderable.rb @@ -14,6 +14,8 @@ module ActionView def render(context, *args) @renderable.render_in(context) + rescue NoMethodError + raise ArgumentError, "'#{@renderable.inspect}' is not a renderable object. It must implement #render_in." end def format diff --git a/actionview/test/template/render_test.rb b/actionview/test/template/render_test.rb index 4462e8d0868..0db3f0593b8 100644 --- a/actionview/test/template/render_test.rb +++ b/actionview/test/template/render_test.rb @@ -293,8 +293,23 @@ module RenderTestCases end def test_render_partial_with_incompatible_object - e = assert_raises(ArgumentError) { @view.render(partial: nil) } - assert_equal "'#{nil.inspect}' is not an ActiveModel-compatible object. It must implement :to_partial_path.", e.message + assert_raises ArgumentError, match: "'#{nil.inspect}' is not an ActiveModel-compatible object. It must implement #to_partial_path." do + @view.render(partial: nil) + end + end + + def test_render_renderable_with_nil + assert_raises ArgumentError, match: "'#{nil.inspect}' is not a renderable object. It must implement #render_in." do + @view.render renderable: nil + end + end + + def test_render_renderable_with_incompatible_object + object = Object.new + + assert_raises ArgumentError, match: "'#{object.inspect}' is not a renderable object. It must implement #render_in." do + @view.render renderable: object + end end def test_render_partial_starting_with_a_capital