Document rendering `:renderable` and `#render_in`

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.
This commit is contained in:
Sean Doyle 2024-01-06 13:27:35 -05:00
parent b294a25a8a
commit 4117583e4b
5 changed files with 50 additions and 7 deletions

View File

@ -39,6 +39,22 @@ module ActionController
# If the first argument responds to +render_in+, the template will be
# rendered by calling +render_in+ with the current view context.
#
# class Greeting
# def render_in(view_context)
# view_context.render html: "<h1>Hello, World</h1>"
# end
#
# def format
# :html
# end
# end
#
# render(Greeting.new)
# # => "<h1>Hello, World</h1>"
#
# render(renderable: Greeting.new)
# # => "<h1>Hello, World</h1>"
#
# ==== \Rendering Mode
#
# [+:partial+]
@ -92,6 +108,14 @@ module ActionController
# render json: { hello: "world" }
# # => renders "{\"hello\":\"world\"}"
#
# [+:renderable+]
# Renders the provided object by calling +render_in+ with the current view
# context. The response format is determined by calling +format+ on the
# renderable if it responds to +format+, falling back to +text/html+ by default.
#
# render renderable: Greeting.new
# # => renders "<h1>Hello, World</h1>"
#
# By default, when a rendering mode is specified, no layout template is
# rendered.
#

View File

@ -73,6 +73,10 @@ class RendererTest < ActiveSupport::TestCase
%(Hello, World!),
renderer.render(TestRenderable.new)
)
assert_equal(
%(Hello, World!),
renderer.render(renderable: TestRenderable.new)
)
end
test "rendering with custom env" do

View File

@ -17,7 +17,7 @@ module ActionView
end
def format
@renderable.format
@renderable.try(:format)
end
end
end

View File

@ -375,6 +375,11 @@ module RenderTestCases
assert_equal "NilClass", @view.render(partial: "test/klass", object: nil)
end
def test_render_renderable_render_in
assert_equal "Hello, World!", @view.render(TestRenderable.new)
assert_equal "Hello, World!", @view.render(renderable: TestRenderable.new)
end
def test_render_object_different_name
assert_equal "Hello: t.lo", @view.render(partial: "test/template_not_named_customer", object: Customer.new("t.lo"), as: "customer").chomp
end

View File

@ -283,18 +283,28 @@ TIP: `send_file` is often a faster and better option if a layout isn't required.
#### Rendering Objects
Rails can render objects responding to `:render_in`.
Rails can render objects responding to `#render_in`. The format can be controlled by defining `#format` on the object.
```ruby
render MyRenderable.new
class Greeting
def render_in(view_context)
view_context.render html: "Hello, World"
end
def format
:html
end
end
render Greeting.new
# => "Hello World"
```
This calls `render_in` on the provided object with the current view context.
You can also provide the object by using the `:renderable` option to `render`:
This calls `render_in` on the provided object with the current view context. You can also provide the object by using the `:renderable` option to `render`:
```ruby
render renderable: MyRenderable.new
render renderable: Greeting.new
# => "Hello World"
```
#### Options for `render`