base.rb 5.5 KB
Newer Older
1
module ActionController
2
  class Base < Metal
3 4 5 6 7 8 9 10 11 12
    abstract!

    include AbstractController::Benchmarker
    include AbstractController::Callbacks
    include AbstractController::Logger

    include ActionController::Helpers
    include ActionController::HideActions
    include ActionController::UrlFor
    include ActionController::Redirector
13 14
    include ActionController::RenderingController
    include ActionController::RenderOptions::All
15 16 17 18 19 20
    include ActionController::Layouts
    include ActionController::ConditionalGet
    include ActionController::RackConvenience

    # Legacy modules
    include SessionManagement
21
    include ActionDispatch::StatusCodes
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
    include ActionController::Caching
    include ActionController::MimeResponds

    # Rails 2.x compatibility
    include ActionController::Rails2Compatibility

    include ActionController::Cookies
    include ActionController::Session
    include ActionController::Flash
    include ActionController::Verification
    include ActionController::RequestForgeryProtection
    include ActionController::Streaming
    include ActionController::HttpAuthentication::Basic::ControllerMethods
    include ActionController::HttpAuthentication::Digest::ControllerMethods
    include ActionController::FilterParameterLogging
    include ActionController::Translation

    # TODO: Extract into its own module
    # This should be moved together with other normalizing behavior
    module ImplicitRender
      def send_action(*)
        ret = super
        default_render unless performed?
        ret
      end

      def default_render
        render
50
      end
51

52 53
      def method_for_action(action_name)
        super || begin
54
          if view_paths.exists?(action_name.to_s, {:formats => formats, :locales => [I18n.locale]}, controller_path)
55 56
            "default_render"
          end
57 58
        end
      end
D
Initial  
David Heinemeier Hansson 已提交
59 60
    end

61
    include ImplicitRender
62

63
    include ActionController::Rescue
64

65 66 67 68
    def self.inherited(klass)
      ::ActionController::Base.subclasses << klass.to_s
      super
    end
69

70 71 72
    def self.subclasses
      @subclasses ||= []
    end
73

74 75 76 77 78 79 80 81
    def _normalize_options(action = nil, options = {}, &blk)
      if action.is_a?(Hash)
        options, action = action, nil
      elsif action.is_a?(String) || action.is_a?(Symbol)
        key = case action = action.to_s
        when %r{^/} then :file
        when %r{/}  then :template
        else             :action
D
Initial  
David Heinemeier Hansson 已提交
82
        end
83 84 85
        options.merge! key => action
      elsif action
        options.merge! :partial => action
D
Initial  
David Heinemeier Hansson 已提交
86
      end
87

88 89
      if options.key?(:action) && options[:action].to_s.index("/")
        options[:template] = options.delete(:action)
90
      end
D
Initial  
David Heinemeier Hansson 已提交
91

92 93
      if options[:status]
        options[:status] = interpret_status(options[:status]).to_i
94
      end
D
Initial  
David Heinemeier Hansson 已提交
95

96 97 98
      options[:update] = blk if block_given?
      options
    end
99

100 101 102 103
    def render(action = nil, options = {}, &blk)
      options = _normalize_options(action, options, &blk)
      super(options)
    end
104

105 106 107 108
    def render_to_string(action = nil, options = {}, &blk)
      options = _normalize_options(action, options, &blk)
      super(options)
    end
109

110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
    # Redirects the browser to the target specified in +options+. This parameter can take one of three forms:
    #
    # * <tt>Hash</tt> - The URL will be generated by calling url_for with the +options+.
    # * <tt>Record</tt> - The URL will be generated by calling url_for with the +options+, which will reference a named URL for that record.
    # * <tt>String</tt> starting with <tt>protocol://</tt> (like <tt>http://</tt>) - Is passed straight through as the target for redirection.
    # * <tt>String</tt> not containing a protocol - The current protocol and host is prepended to the string.
    # * <tt>:back</tt> - Back to the page that issued the request. Useful for forms that are triggered from multiple places.
    #   Short-hand for <tt>redirect_to(request.env["HTTP_REFERER"])</tt>
    #
    # Examples:
    #   redirect_to :action => "show", :id => 5
    #   redirect_to post
    #   redirect_to "http://www.rubyonrails.org"
    #   redirect_to "/images/screenshot.jpg"
    #   redirect_to articles_url
    #   redirect_to :back
    #
    # The redirection happens as a "302 Moved" header unless otherwise specified.
    #
    # Examples:
    #   redirect_to post_url(@post), :status=>:found
    #   redirect_to :action=>'atom', :status=>:moved_permanently
    #   redirect_to post_url(@post), :status=>301
    #   redirect_to :action=>'atom', :status=>302
    #
    # When using <tt>redirect_to :back</tt>, if there is no referrer,
    # RedirectBackError will be raised. You may specify some fallback
    # behavior for this case by rescuing RedirectBackError.
    def redirect_to(options = {}, response_status = {}) #:doc:
      raise ActionControllerError.new("Cannot redirect to nil!") if options.nil?

      status = if options.is_a?(Hash) && options.key?(:status)
        interpret_status(options.delete(:status))
      elsif response_status.key?(:status)
        interpret_status(response_status[:status])
      else
        302
      end

      url = case options
      # The scheme name consist of a letter followed by any combination of
      # letters, digits, and the plus ("+"), period ("."), or hyphen ("-")
      # characters; and is terminated by a colon (":").
      when %r{^\w[\w\d+.-]*:.*}
        options
      when String
        request.protocol + request.host_with_port + options
      when :back
        raise RedirectBackError unless refer = request.headers["Referer"]
        refer
      else
        url_for(options)
      end

      super(url, status)
165
    end
166
  end
J
Jeremy Kemper 已提交
167
end