aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_view/renderer/renderer.rb
blob: f0ee103d805efe05b25eea8496c8ab4e94d1e89e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
module ActionView
  # This is the main entry point for rendering. It basically delegates
  # to other objects like TemplateRenderer and PartialRenderer which
  # actually renders the template.
  class Renderer
    attr_accessor :lookup_context

    # TODO: render_context should not be an initialization parameter
    def initialize(lookup_context, render_context)
      @render_context = render_context
      @lookup_context = lookup_context
      @view_flow = OutputFlow.new
    end

    # Returns the result of a render that's dictated by the options hash. The primary options are:
    #
    # * <tt>:partial</tt> - See ActionView::Partials.
    # * <tt>:file</tt> - Renders an explicit template file (this used to be the old default), add :locals to pass in those.
    # * <tt>:inline</tt> - Renders an inline template similar to how it's done in the controller.
    # * <tt>:text</tt> - Renders the text passed in out.
    #
    # If no options hash is passed or :update specified, the default is to render a partial and use the second parameter
    # as the locals hash.
    def render(options = {}, locals = {}, &block)
      case options
      when Hash
        if block_given?
          _render_partial(options.merge(:partial => options[:layout]), &block)
        elsif options.key?(:partial)
          _render_partial(options)
        else
          _render_template(options)
        end
      else
        _render_partial(:partial => options, :locals => locals)
      end
    end

    # Render but returns a valid Rack body. If fibers are defined, we return
    # a streaming body that renders the template piece by piece.
    #
    # Note that partials are not supported to be rendered with streaming,
    # so in such cases, we just wrap them in an array.
    def render_body(options)
      if options.key?(:partial)
        [_render_partial(options)]
      else
        StreamingTemplateRenderer.new(@render_context, @lookup_context).render(options)
      end
    end

    private

    def _render_template(options) #:nodoc:
      _template_renderer.render(options)
    end

    def _template_renderer #:nodoc:
      @_template_renderer ||= TemplateRenderer.new(@render_context, @lookup_context)
    end

    def _render_partial(options, &block) #:nodoc:
      _partial_renderer.setup(options, block).render
    end

    def _partial_renderer #:nodoc:
      @_partial_renderer ||= PartialRenderer.new(@render_context, @lookup_context)
    end
  end
end