Repository navigation
Document rendering :renderable and #render_in - #50622
Conversation
0169b58 to
cadcb88
Compare
Provide examples for rendering objects that respond to `render_in`. Also highlight that the object can also define a `#format` method to control how the rendered String should be treated. Add test coverage for both Action View's and Action Pack's support for `render` with `:renderable` options.
cadcb88 to
4117583
Compare
|
|
||
| def format | ||
| @renderable.format | ||
| @renderable.try(:format) |
| def test_render_renderable_render_in | ||
| assert_equal "Hello, World!", @view.render(TestRenderable.new) | ||
| assert_equal "Hello, World!", @view.render(renderable: TestRenderable.new) | ||
| end |
There was a problem hiding this comment.
@p8 yes, this addition combined with this change fails the suite:
--- a/actionview/lib/action_view/template/renderable.rb
+++ b/actionview/lib/action_view/template/renderable.rb
@@ -17,7 +17,7 @@ def render(context, *args)
end
def format
- @renderable.try(:format)
+ @renderable.format
end
end
endRunning 3020 tests in parallel using 12 processes
Run options: --seed 64876
# Running:
....................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................E
Error:
CachedCollectionViewRenderTest#test_render_renderable_render_in:
NoMethodError: private method `format' called for #<TestRenderable:0x000000010add4270>
/Users/seanpdoyle/Work/rails/rails/actionview/lib/action_view/template/renderable.rb:20:in `format'
/Users/seanpdoyle/Work/rails/rails/actionview/lib/action_view/renderer/template_renderer.rb:9:in `render'
/Users/seanpdoyle/Work/rails/rails/actionview/lib/action_view/renderer/renderer.rb:58:in `render_template_to_object'
/Users/seanpdoyle/Work/rails/rails/actionview/lib/action_view/renderer/renderer.rb:31:in `render_to_object'
/Users/seanpdoyle/Work/rails/rails/actionview/lib/action_view/renderer/renderer.rb:24:in `render'
/Users/seanpdoyle/Work/rails/rails/actionview/lib/action_view/helpers/rendering_helper.rb:37:in `block in render'
/Users/seanpdoyle/Work/rails/rails/actionview/lib/action_view/base.rb:291:in `in_rendering_context'
/Users/seanpdoyle/Work/rails/rails/actionview/lib/action_view/helpers/rendering_helper.rb:33:in `render'
/Users/seanpdoyle/Work/rails/rails/actionview/test/template/render_test.rb:380:in `test_render_renderable_render_in'
bin/test test/template/render_test.rb:378
.......................................................................................................................................................E
Error:
FrozenStringLiteralEnabledViewRenderTest#test_render_renderable_render_in:
NoMethodError: private method `format' called for #<TestRenderable:0x0000000105277670>
/Users/seanpdoyle/Work/rails/rails/actionview/lib/action_view/template/renderable.rb:20:in `format'
/Users/seanpdoyle/Work/rails/rails/actionview/lib/action_view/renderer/template_renderer.rb:9:in `render'
/Users/seanpdoyle/Work/rails/rails/actionview/lib/action_view/renderer/renderer.rb:58:in `render_template_to_object'
/Users/seanpdoyle/Work/rails/rails/actionview/lib/action_view/renderer/renderer.rb:31:in `render_to_object'
/Users/seanpdoyle/Work/rails/rails/actionview/lib/action_view/renderer/renderer.rb:24:in `render'
/Users/seanpdoyle/Work/rails/rails/actionview/lib/action_view/helpers/rendering_helper.rb:37:in `block in render'
/Users/seanpdoyle/Work/rails/rails/actionview/lib/action_view/base.rb:291:in `in_rendering_context'
/Users/seanpdoyle/Work/rails/rails/actionview/lib/action_view/helpers/rendering_helper.rb:33:in `render'
/Users/seanpdoyle/Work/rails/rails/actionview/test/template/render_test.rb:380:in `test_render_renderable_render_in'
bin/test test/template/render_test.rb:378
.......................................................................................................................................................................................................................................................................................................................................................................................................................................................................E
Error:
LazyViewRenderTest#test_render_renderable_render_in:
NoMethodError: private method `format' called for #<TestRenderable:0x000000010a7d10d0>
/Users/seanpdoyle/Work/rails/rails/actionview/lib/action_view/template/renderable.rb:20:in `format'
/Users/seanpdoyle/Work/rails/rails/actionview/lib/action_view/renderer/template_renderer.rb:9:in `render'
/Users/seanpdoyle/Work/rails/rails/actionview/lib/action_view/renderer/renderer.rb:58:in `render_template_to_object'
/Users/seanpdoyle/Work/rails/rails/actionview/lib/action_view/renderer/renderer.rb:31:in `render_to_object'
/Users/seanpdoyle/Work/rails/rails/actionview/lib/action_view/renderer/renderer.rb:24:in `render'
/Users/seanpdoyle/Work/rails/rails/actionview/lib/action_view/helpers/rendering_helper.rb:37:in `block in render'
/Users/seanpdoyle/Work/rails/rails/actionview/lib/action_view/base.rb:291:in `in_rendering_context'
/Users/seanpdoyle/Work/rails/rails/actionview/lib/action_view/helpers/rendering_helper.rb:33:in `render'
/Users/seanpdoyle/Work/rails/rails/actionview/test/template/render_test.rb:380:in `test_render_renderable_render_in'
bin/test test/template/render_test.rb:378
...............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................E
Error:
CachedViewRenderTest#test_render_renderable_render_in:
NoMethodError: private method `format' called for #<TestRenderable:0x000000010a4b01f8>
/Users/seanpdoyle/Work/rails/rails/actionview/lib/action_view/template/renderable.rb:20:in `format'
/Users/seanpdoyle/Work/rails/rails/actionview/lib/action_view/renderer/template_renderer.rb:9:in `render'
/Users/seanpdoyle/Work/rails/rails/actionview/lib/action_view/renderer/renderer.rb:58:in `render_template_to_object'
/Users/seanpdoyle/Work/rails/rails/actionview/lib/action_view/renderer/renderer.rb:31:in `render_to_object'
/Users/seanpdoyle/Work/rails/rails/actionview/lib/action_view/renderer/renderer.rb:24:in `render'
/Users/seanpdoyle/Work/rails/rails/actionview/lib/action_view/helpers/rendering_helper.rb:37:in `block in render'
/Users/seanpdoyle/Work/rails/rails/actionview/lib/action_view/base.rb:291:in `in_rendering_context'
/Users/seanpdoyle/Work/rails/rails/actionview/lib/action_view/helpers/rendering_helper.rb:33:in `render'
/Users/seanpdoyle/Work/rails/rails/actionview/test/template/render_test.rb:380:in `test_render_renderable_render_in'
bin/test test/template/render_test.rb:378
.......................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
Finished in 1.125893s, 2682.3153 runs/s, 5853.1317 assertions/s.
3020 runs, 6590 assertions, 0 failures, 4 errors, 0 skips
Given the fact that this PR documented an implicit public API, I opted to make the API conditional rather than make this change instead:
diff --git a/actionview/lib/action_view/template/renderable.rb b/actionview/lib/action_view/template/renderable.rb
index c37bd1cb5e..52af19f947 100644
--- a/actionview/lib/action_view/template/renderable.rb
+++ b/actionview/lib/action_view/template/renderable.rb
@@ -17,7 +17,7 @@ def render(context, *args)
end
def format
- @renderable.try(:format)
+ @renderable.format
end
end
end
diff --git a/actionview/test/lib/test_renderable.rb b/actionview/test/lib/test_renderable.rb
index c2b7411e14..46e2f8983c 100644
--- a/actionview/test/lib/test_renderable.rb
+++ b/actionview/test/lib/test_renderable.rb
@@ -4,4 +4,8 @@ class TestRenderable
def render_in(_view_context)
"Hello, World!"
end
+
+ def format
+ :html
+ end
endDo we think that it's worthwhile to remove the call to #try as part of #50623?
There was a problem hiding this comment.
Hmm, interesting. I wasn't aware try allows calling private methods.
If format is expected in the Renderable API shouldn't if be public always?
Edit: Sorry, try returns nil for private methods. I think that might be unexpected in this case.
There was a problem hiding this comment.
@p8 the call to .try(:format) is returning nil because it's treating @renderable as if it doesn't respond to #format.
If the object doesn't define its own #format method, then the private method references Kernel#format:
CachedViewRenderTest#test_render_renderable_render_in:
RuntimeError: #format defined at: #<Method: TestRenderable(Kernel)#format(*)>
That failure is raised by this change:
diff --git a/actionview/lib/action_view/template/renderable.rb b/actionview/lib/action_view/template/renderable.rb
index c37bd1cb5e..bec7ea5fba 100644
--- a/actionview/lib/action_view/template/renderable.rb
+++ b/actionview/lib/action_view/template/renderable.rb
@@ -17,7 +17,8 @@ def render(context, *args)
end
def format
- @renderable.try(:format)
+ fail "#format defined at: #{@renderable.method(:format)}"
end
end
endIf
formatis expected in the Renderable API shouldn't if be public always?
Is that a breaking change? Should this .try(:format) be accompanied by a deprecation warning that we can remove later?
There was a problem hiding this comment.
The private format in question here is Kernel#format. This code is correct, there is no need for deprecations.
Motivation / Background
Provide examples for rendering objects that respond to
render_in. Also highlight that the object can also define a#formatmethod to control how the rendered String should be treated.Detail
Add test coverage for both Action View's and Action Pack's support for
renderwith:renderableoptions.