class ActionView::Renderer

each time render is called.
the setup and logic necessary to render a view and a new object is created
TemplateRenderer and PartialRenderer objects are wrappers which do all
method and render a partial or a template based on the options. The
The Renderer will parse the options from the render or render_body
actually renders the template.
to other objects like TemplateRenderer and PartialRenderer which
This is the main entry point for rendering. It basically delegates

def cache_hits # :nodoc:

:nodoc:
def cache_hits # :nodoc:
  @cache_hits ||= {}
end

def initialize(lookup_context)

def initialize(lookup_context)
  @lookup_context = lookup_context
end

def render(context, options)

Main render entry point shared by Action View and Action Controller.
def render(context, options)
  if options.key?(:partial)
    render_partial(context, options)
  else
    render_template(context, options)
  end
end

def render_body(context, options)

so in such cases, we just wrap them in an array.
Note that partials are not supported to be rendered with streaming,

a streaming body that renders the template piece by piece.
Render but returns a valid Rack body. If fibers are defined, we return
def render_body(context, options)
  if options.key?(:partial)
    [render_partial(context, options)]
  else
    StreamingTemplateRenderer.new(@lookup_context).render(context, options)
  end
end

def render_partial(context, options, &block) #:nodoc:

:nodoc:
Direct access to partial rendering.
def render_partial(context, options, &block) #:nodoc:
  PartialRenderer.new(@lookup_context).render(context, options, block)
end

def render_template(context, options) #:nodoc:

:nodoc:
Direct access to template rendering.
def render_template(context, options) #:nodoc:
  TemplateRenderer.new(@lookup_context).render(context, options)
end