renderer.rb 2.6 KB
Newer Older
1 2
require "action_controller/abstract/logger"

3 4
module AbstractController
  module Renderer
5
    extend ActiveSupport::Concern
J
Joshua Peek 已提交
6

7
    include AbstractController::Logger
8 9

    included do
10
      attr_internal :formats
11

12
      extlib_inheritable_accessor :_view_paths
13

14
      self._view_paths ||= ActionView::PathSet.new
15
    end
16

17
    def _action_view
J
Joshua Peek 已提交
18
      @_action_view ||= ActionView::Base.new(self.class.view_paths, {}, self)
19
    end
J
Joshua Peek 已提交
20

21
    def render(*args)
Y
Yehuda Katz 已提交
22
      if response_body
23 24
        raise AbstractController::DoubleRenderError, "OMG"
      end
J
Joshua Peek 已提交
25

26
      self.response_body = render_to_body(*args)
27
    end
J
Joshua Peek 已提交
28

29
    # Raw rendering of a template to a Rack-compatible body.
Y
Yehuda Katz 已提交
30 31 32
    # ====
    # @option _prefix<String> The template's path prefix
    # @option _layout<String> The relative path to the layout template to use
J
Joshua Peek 已提交
33
    #
Y
Yehuda Katz 已提交
34
    # :api: plugin
35
    def render_to_body(options = {})
36 37 38
      # TODO: Refactor so we can just use the normal template logic for this
      if options[:_partial_object]
        _action_view._render_partial_from_controller(options)
39 40 41
      else
        _determine_template(options)
        _render_template(options)
42
      end
43 44
    end

45 46 47 48
    # Raw rendering of a template to a string.
    # ====
    # @option _prefix<String> The template's path prefix
    # @option _layout<String> The relative path to the layout template to use
J
Joshua Peek 已提交
49
    #
50 51
    # :api: plugin
    def render_to_string(options = {})
52
      AbstractController::Renderer.body_to_s(render_to_body(options))
53 54
    end

55 56
    def _render_template(options)
      _action_view._render_template_from_controller(options[:_template], options[:_layout], options, options[:_partial])
57
    end
J
Joshua Peek 已提交
58 59 60 61

    def view_paths()
      _view_paths
    end
62

63 64 65 66 67 68 69 70 71 72 73 74
    # Return a string representation of a Rack-compatible response body.
    def self.body_to_s(body)
      if body.respond_to?(:to_str)
        body
      else
        strings = []
        body.each { |part| strings << part.to_s }
        body.close if body.respond_to?(:close)
        strings.join
      end
    end

75 76 77 78 79 80 81 82 83
  private
    def _determine_template(options)
      name = (options[:_template_name] || action_name).to_s

      options[:_template] ||= view_paths.find_by_parts(
        name, { :formats => formats }, options[:_prefix], options[:_partial]
      )
    end

84 85 86 87
    module ClassMethods
      def append_view_path(path)
        self.view_paths << path
      end
J
Joshua Peek 已提交
88

89 90 91 92
      def prepend_view_path(path)
        self.view_paths.unshift(path)
      end

Y
Yehuda Katz 已提交
93 94 95
      def view_paths
        self._view_paths
      end
J
Joshua Peek 已提交
96

Y
Yehuda Katz 已提交
97 98 99 100
      def view_paths=(paths)
        self._view_paths = paths.is_a?(ActionView::PathSet) ?
                            paths : ActionView::Base.process_view_paths(paths)
      end
101 102
    end
  end
103
end