diff options
Diffstat (limited to 'actionpack/lib')
25 files changed, 552 insertions, 128 deletions
diff --git a/actionpack/lib/action_controller/abstract/base.rb b/actionpack/lib/action_controller/abstract/base.rb index ade7719cc0..ab9aed0b26 100644 --- a/actionpack/lib/action_controller/abstract/base.rb +++ b/actionpack/lib/action_controller/abstract/base.rb @@ -4,13 +4,44 @@ module AbstractController attr_internal :response_body attr_internal :response_obj attr_internal :action_name - - def self.process(action) - new.process(action) + + class << self + attr_reader :abstract + + def abstract! + @abstract = true + end + + alias_method :abstract?, :abstract + + def internal_methods + controller = self + controller = controller.superclass until controller.abstract? + controller.public_instance_methods(true) + end + + def process(action) + new.process(action.to_s) + end + + def hidden_actions + [] + end + + def action_methods + @action_methods ||= + # All public instance methods of this class, including ancestors + public_instance_methods(true).map { |m| m.to_s }.to_set - + # Except for public instance methods of Base and its ancestors + internal_methods.map { |m| m.to_s } + + # Be sure to include shadowed public instance methods of this class + public_instance_methods(false).map { |m| m.to_s } - + # And always exclude explicitly hidden actions + hidden_actions + end end - def self.inherited(klass) - end + abstract! def initialize self.response_obj = {} @@ -23,19 +54,32 @@ module AbstractController @_action_name = action_name process_action - self.response_obj[:body] = self.response_body self end private + def action_methods + self.class.action_methods + end + + # It is possible for respond_to?(action_name) to be false and + # respond_to?(:action_missing) to be false if respond_to_action? + # is overridden in a subclass. For instance, ActionController::Base + # overrides it to include the case where a template matching the + # action_name is found. def process_action - respond_to?(action_name) ? send(action_name) : send(:action_missing, action_name) + if respond_to?(action_name) then send(action_name) + elsif respond_to?(:action_missing, true) then action_missing(action_name) + end end + # Override this to change the conditions that will raise an + # ActionNotFound error. If you accept a difference case, + # you must handle it by also overriding process_action and + # handling the case. def respond_to_action?(action_name) - respond_to?(action_name) || respond_to?(:action_missing, true) + action_methods.include?(action_name) || respond_to?(:action_missing, true) end - end end
\ No newline at end of file diff --git a/actionpack/lib/action_controller/abstract/callbacks.rb b/actionpack/lib/action_controller/abstract/callbacks.rb index d7faaf4236..6e15b3e81b 100644 --- a/actionpack/lib/action_controller/abstract/callbacks.rb +++ b/actionpack/lib/action_controller/abstract/callbacks.rb @@ -17,11 +17,11 @@ module AbstractController module ClassMethods def _normalize_callback_options(options) if only = options[:only] - only = Array(only).map {|o| "action_name == :#{o}"}.join(" || ") + only = Array(only).map {|o| "action_name == '#{o}'"}.join(" || ") options[:per_key] = {:if => only} end if except = options[:except] - except = Array(except).map {|e| "action_name == :#{e}"}.join(" || ") + except = Array(except).map {|e| "action_name == '#{e}'"}.join(" || ") options[:per_key] = {:unless => except} end end diff --git a/actionpack/lib/action_controller/abstract/helpers.rb b/actionpack/lib/action_controller/abstract/helpers.rb index 62caa119e7..968d3080c1 100644 --- a/actionpack/lib/action_controller/abstract/helpers.rb +++ b/actionpack/lib/action_controller/abstract/helpers.rb @@ -8,14 +8,7 @@ module AbstractController extlib_inheritable_accessor :master_helper_module self.master_helper_module = Module.new end - - # def self.included(klass) - # klass.class_eval do - # extlib_inheritable_accessor :master_helper_module - # self.master_helper_module = Module.new - # end - # end - + def _action_view @_action_view ||= begin av = super diff --git a/actionpack/lib/action_controller/abstract/layouts.rb b/actionpack/lib/action_controller/abstract/layouts.rb index 76130f8dc0..e48b8b2b4b 100644 --- a/actionpack/lib/action_controller/abstract/layouts.rb +++ b/actionpack/lib/action_controller/abstract/layouts.rb @@ -51,13 +51,16 @@ module AbstractController end def _render_template(template, options) - _action_view._render_template_with_layout(template, options[:_layout]) + _action_view._render_template_with_layout(template, options[:_layout], options) end private def _layout() end # This will be overwritten + # :api: plugin + # ==== + # Override this to mutate the inbound layout name def _layout_for_name(name) unless [String, FalseClass, NilClass].include?(name.class) raise ArgumentError, "String, false, or nil expected; you passed #{name.inspect}" @@ -68,10 +71,10 @@ module AbstractController def _default_layout(require_layout = false) if require_layout && !_layout - raise ArgumentError, + raise ArgumentError, "There was no default layout for #{self.class} in #{view_paths.inspect}" end - + begin layout = _layout_for_name(_layout) rescue NameError => e diff --git a/actionpack/lib/action_controller/abstract/renderer.rb b/actionpack/lib/action_controller/abstract/renderer.rb index beb848f90e..b58688c9da 100644 --- a/actionpack/lib/action_controller/abstract/renderer.rb +++ b/actionpack/lib/action_controller/abstract/renderer.rb @@ -1,6 +1,15 @@ require "action_controller/abstract/logger" module AbstractController + class AbstractControllerError < StandardError; end + class DoubleRenderError < AbstractControllerError + DEFAULT_MESSAGE = "Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like \"redirect_to(...) and return\"." + + def initialize(message = nil) + super(message || DEFAULT_MESSAGE) + end + end + module Renderer extend ActiveSupport::DependencyModule @@ -19,6 +28,10 @@ module AbstractController end def render(options = {}) + if response_body + raise AbstractController::DoubleRenderError, "OMG" + end + self.response_body = render_to_body(options) end @@ -31,8 +44,9 @@ module AbstractController def render_to_body(options = {}) name = options[:_template_name] || action_name - template = options[:_template] || view_paths.find_by_parts(name.to_s, {:formats => formats}, options[:_prefix]) - _render_template(template, options) + options[:_template] ||= view_paths.find_by_parts(name.to_s, {:formats => formats}, options[:_prefix]) + + _render_template(options[:_template], options) end # Raw rendering of a template to a string. diff --git a/actionpack/lib/action_controller/base/base.rb b/actionpack/lib/action_controller/base/base.rb index 7bbde519cc..d25801b17b 100644 --- a/actionpack/lib/action_controller/base/base.rb +++ b/actionpack/lib/action_controller/base/base.rb @@ -365,17 +365,23 @@ module ActionController #:nodoc: attr_reader :template - class << self - def call(env) - new.call(env) - end + def action(name, env) + # HACK: For global rescue to have access to the original request and response + request = env["action_controller.rescue.request"] ||= ActionDispatch::Request.new(env) + response = env["action_controller.rescue.response"] ||= ActionDispatch::Response.new + self.action_name = name && name.to_s + process(request, response).to_a + end - # Factory for the standard create, process loop where the controller is discarded after processing. - def process(request, response) #:nodoc: - ActiveSupport::Deprecation.warn("Controller.process has been deprecated. Use Controller.call instead", caller) - new.process(request, response) - end + class << self + def action(name = nil) + @actions ||= {} + @actions[name] ||= proc do |env| + new.action(name, env) + end + end + # Converts the class name from something like "OneModule::TwoModule::NeatController" to "NeatController". def controller_class_name @controller_class_name ||= name.demodulize @@ -518,7 +524,6 @@ module ActionController #:nodoc: assign_shortcuts(request, response) initialize_template_class(response) initialize_current_url - assign_names log_processing send(method, *arguments) @@ -882,10 +887,6 @@ module ActionController #:nodoc: @performed_render || @performed_redirect end - def assign_names - @action_name = (params['action'] || 'index') - end - def reset_variables_added_to_assigns @template.instance_variable_set("@assigns_added", nil) end diff --git a/actionpack/lib/action_controller/dispatch/dispatcher.rb b/actionpack/lib/action_controller/dispatch/dispatcher.rb index cce3b6175d..63866caed9 100644 --- a/actionpack/lib/action_controller/dispatch/dispatcher.rb +++ b/actionpack/lib/action_controller/dispatch/dispatcher.rb @@ -48,7 +48,7 @@ module ActionController cattr_accessor :middleware self.middleware = ActionDispatch::MiddlewareStack.new do |middleware| middlewares = File.join(File.dirname(__FILE__), "middlewares.rb") - middleware.instance_eval(File.read(middlewares)) + middleware.instance_eval(File.read(middlewares), middlewares, 1) end include ActiveSupport::Callbacks diff --git a/actionpack/lib/action_controller/dispatch/middlewares.rb b/actionpack/lib/action_controller/dispatch/middlewares.rb index 31a7b00d28..f99637b109 100644 --- a/actionpack/lib/action_controller/dispatch/middlewares.rb +++ b/actionpack/lib/action_controller/dispatch/middlewares.rb @@ -14,4 +14,4 @@ use lambda { ActionController::Base.session_store }, use "ActionDispatch::ParamsParser" use "Rack::MethodOverride" -use "Rack::Head" +use "Rack::Head"
\ No newline at end of file diff --git a/actionpack/lib/action_controller/new_base.rb b/actionpack/lib/action_controller/new_base.rb index 7c65f1cdc1..8a7de1476c 100644 --- a/actionpack/lib/action_controller/new_base.rb +++ b/actionpack/lib/action_controller/new_base.rb @@ -1,7 +1,27 @@ module ActionController - autoload :AbstractBase, "action_controller/new_base/base" - autoload :HideActions, "action_controller/new_base/hide_actions" - autoload :Layouts, "action_controller/new_base/layouts" - autoload :Renderer, "action_controller/new_base/renderer" - autoload :UrlFor, "action_controller/new_base/url_for" -end
\ No newline at end of file + autoload :Base, "action_controller/new_base/base" + autoload :ConditionalGet, "action_controller/new_base/conditional_get" + autoload :HideActions, "action_controller/new_base/hide_actions" + autoload :Http, "action_controller/new_base/http" + autoload :Layouts, "action_controller/new_base/layouts" + autoload :Rails2Compatibility, "action_controller/new_base/compatibility" + autoload :Renderer, "action_controller/new_base/renderer" + autoload :Testing, "action_controller/new_base/testing" + autoload :UrlFor, "action_controller/new_base/url_for" + + # Ported modules + # require 'action_controller/routing' + autoload :Dispatcher, 'action_controller/dispatch/dispatcher' + autoload :PolymorphicRoutes, 'action_controller/routing/generation/polymorphic_routes' + autoload :RecordIdentifier, 'action_controller/record_identifier' + autoload :Resources, 'action_controller/routing/resources' + autoload :SessionManagement, 'action_controller/base/session_management' + autoload :TestCase, 'action_controller/testing/test_case' + autoload :UrlRewriter, 'action_controller/routing/generation/url_rewriter' + autoload :UrlWriter, 'action_controller/routing/generation/url_rewriter' + + require 'action_controller/routing' +end + +require 'action_dispatch' +require 'action_view'
\ No newline at end of file diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb index 08e7a1a0e7..4892886341 100644 --- a/actionpack/lib/action_controller/new_base/base.rb +++ b/actionpack/lib/action_controller/new_base/base.rb @@ -1,60 +1,62 @@ module ActionController - class AbstractBase < AbstractController::Base - - # :api: public - attr_internal :request, :response, :params - - # :api: public - def self.controller_name - @controller_name ||= controller_path.split("/").last - end - - # :api: public - def controller_name() self.class.controller_name end - - # :api: public - def self.controller_path - @controller_path ||= self.name.sub(/Controller$/, '').underscore - end + class Base < Http + abstract! - # :api: public - def controller_path() self.class.controller_path end - - # :api: private - def self.action_methods - @action_names ||= Set.new(self.public_instance_methods - self::CORE_METHODS) + include AbstractController::Callbacks + include AbstractController::Helpers + include AbstractController::Logger + + include ActionController::HideActions + include ActionController::UrlFor + include ActionController::Renderer + include ActionController::Layouts + include ActionController::ConditionalGet + + # Legacy modules + include SessionManagement + include ActionDispatch::StatusCodes + + # Rails 2.x compatibility + include ActionController::Rails2Compatibility + + def self.inherited(klass) + ::ActionController::Base.subclasses << klass.to_s + super end - # :api: private - def self.action_names() action_methods end + def self.subclasses + @subclasses ||= [] + end - # :api: private - def action_methods() self.class.action_names end - - # :api: private - def action_names() action_methods end + def self.app_loaded! + @subclasses.each do |subclass| + subclass.constantize._write_layout_method + end + end - # :api: plugin - def self.call(env) - controller = new - controller.call(env).to_rack + def render(action = action_name, options = {}) + if action.is_a?(Hash) + options, action = action, nil + else + options.merge! :action => action + end + + super(options) end - # :api: plugin - def response_body=(body) - @_response.body = body + def render_to_body(options = {}) + options = {:template => options} if options.is_a?(String) + super end - # :api: private - def call(env) - @_request = ActionDispatch::Request.new(env) - @_response = ActionDispatch::Response.new - process(@_request.parameters[:action]) + def process_action + ret = super + render if response_body.nil? + ret end - # :api: private - def to_rack - response.to_a + def respond_to_action?(action_name) + super || view_paths.find_by_parts?(action_name.to_s, {:formats => formats, :locales => [I18n.locale]}, controller_path) end end -end +end
\ No newline at end of file diff --git a/actionpack/lib/action_controller/new_base/compatibility.rb b/actionpack/lib/action_controller/new_base/compatibility.rb new file mode 100644 index 0000000000..4655a94923 --- /dev/null +++ b/actionpack/lib/action_controller/new_base/compatibility.rb @@ -0,0 +1,58 @@ +module ActionController + module Rails2Compatibility + extend ActiveSupport::DependencyModule + + # Temporary hax + included do + ::ActionController::UnknownAction = ::AbstractController::ActionNotFound + ::ActionController::DoubleRenderError = ::AbstractController::DoubleRenderError + + cattr_accessor :session_options + self.send(:class_variable_set, "@@session_options", {}) + + cattr_accessor :allow_concurrency + self.send(:class_variable_set, "@@allow_concurrency", false) + + cattr_accessor :param_parsers + self.send(:class_variable_set, "@@param_parsers", { Mime::MULTIPART_FORM => :multipart_form, + Mime::URL_ENCODED_FORM => :url_encoded_form, + Mime::XML => :xml_simple, + Mime::JSON => :json }) + + cattr_accessor :relative_url_root + self.send(:class_variable_set, "@@relative_url_root", ENV['RAILS_RELATIVE_URL_ROOT']) + + cattr_accessor :default_charset + self.send(:class_variable_set, "@@default_charset", "utf-8") + + cattr_reader :protected_instance_variables + self.send(:class_variable_set, "@@protected_instance_variables", %w(@assigns @performed_redirect @performed_render @variables_added @request_origin @url @parent_controller + @action_name @before_filter_chain_aborted @action_cache_path @_headers @_params + @_flash @_response)) + end + + module ClassMethods + def protect_from_forgery() end + def consider_all_requests_local() end + def rescue_action(env) + raise env["action_dispatch.rescue.exception"] + end + end + + def render_to_body(options) + if options.is_a?(Hash) && options.key?(:template) + options[:template].sub!(/^\//, '') + end + + options[:text] = nil if options[:nothing] == true + + super + end + + def _layout_for_name(name) + name &&= name.sub(%r{^/?layouts/}, '') + super + end + + end +end
\ No newline at end of file diff --git a/actionpack/lib/action_controller/new_base/conditional_get.rb b/actionpack/lib/action_controller/new_base/conditional_get.rb new file mode 100644 index 0000000000..e1407e671a --- /dev/null +++ b/actionpack/lib/action_controller/new_base/conditional_get.rb @@ -0,0 +1,131 @@ +module ActionController + module ConditionalGet + + # Sets the etag, last_modified, or both on the response and renders a + # "304 Not Modified" response if the request is already fresh. + # + # Parameters: + # * <tt>:etag</tt> + # * <tt>:last_modified</tt> + # * <tt>:public</tt> By default the Cache-Control header is private, set this to true if you want your application to be cachable by other devices (proxy caches). + # + # Example: + # + # def show + # @article = Article.find(params[:id]) + # fresh_when(:etag => @article, :last_modified => @article.created_at.utc, :public => true) + # end + # + # This will render the show template if the request isn't sending a matching etag or + # If-Modified-Since header and just a "304 Not Modified" response if there's a match. + # + def fresh_when(options) + options.assert_valid_keys(:etag, :last_modified, :public) + + response.etag = options[:etag] if options[:etag] + response.last_modified = options[:last_modified] if options[:last_modified] + + if options[:public] + cache_control = response.headers["Cache-Control"].split(",").map {|k| k.strip } + cache_control.delete("private") + cache_control.delete("no-cache") + cache_control << "public" + response.headers["Cache-Control"] = cache_control.join(', ') + end + + if request.fresh?(response) + head :not_modified + end + end + + # Return a response that has no content (merely headers). The options + # argument is interpreted to be a hash of header names and values. + # This allows you to easily return a response that consists only of + # significant headers: + # + # head :created, :location => person_path(@person) + # + # It can also be used to return exceptional conditions: + # + # return head(:method_not_allowed) unless request.post? + # return head(:bad_request) unless valid_request? + # render + def head(*args) + if args.length > 2 + raise ArgumentError, "too many arguments to head" + elsif args.empty? + raise ArgumentError, "too few arguments to head" + end + options = args.extract_options! + status = interpret_status(args.shift || options.delete(:status) || :ok) + + options.each do |key, value| + headers[key.to_s.dasherize.split(/-/).map { |v| v.capitalize }.join("-")] = value.to_s + end + + render :nothing => true, :status => status + end + + # Sets the etag and/or last_modified on the response and checks it against + # the client request. If the request doesn't match the options provided, the + # request is considered stale and should be generated from scratch. Otherwise, + # it's fresh and we don't need to generate anything and a reply of "304 Not Modified" is sent. + # + # Parameters: + # * <tt>:etag</tt> + # * <tt>:last_modified</tt> + # * <tt>:public</tt> By default the Cache-Control header is private, set this to true if you want your application to be cachable by other devices (proxy caches). + # + # Example: + # + # def show + # @article = Article.find(params[:id]) + # + # if stale?(:etag => @article, :last_modified => @article.created_at.utc) + # @statistics = @article.really_expensive_call + # respond_to do |format| + # # all the supported formats + # end + # end + # end + def stale?(options) + fresh_when(options) + !request.fresh?(response) + end + + # Sets a HTTP 1.1 Cache-Control header. Defaults to issuing a "private" instruction, so that + # intermediate caches shouldn't cache the response. + # + # Examples: + # expires_in 20.minutes + # expires_in 3.hours, :public => true + # expires in 3.hours, 'max-stale' => 5.hours, :public => true + # + # This method will overwrite an existing Cache-Control header. + # See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html for more possibilities. + def expires_in(seconds, options = {}) #:doc: + cache_control = response.headers["Cache-Control"].split(",").map {|k| k.strip } + + cache_control << "max-age=#{seconds}" + cache_control.delete("no-cache") + if options[:public] + cache_control.delete("private") + cache_control << "public" + else + cache_control << "private" + end + + # This allows for additional headers to be passed through like 'max-stale' => 5.hours + cache_control += options.symbolize_keys.reject{|k,v| k == :public || k == :private }.map{ |k,v| v == true ? k.to_s : "#{k.to_s}=#{v.to_s}"} + + response.headers["Cache-Control"] = cache_control.join(', ') + end + + # Sets a HTTP 1.1 Cache-Control header of "no-cache" so no caching should occur by the browser or + # intermediate caches (like caching proxy servers). + def expires_now #:doc: + response.headers["Cache-Control"] = "no-cache" + end + + end +end
\ No newline at end of file diff --git a/actionpack/lib/action_controller/new_base/hide_actions.rb b/actionpack/lib/action_controller/new_base/hide_actions.rb index aa420442fb..d1857a9169 100644 --- a/actionpack/lib/action_controller/new_base/hide_actions.rb +++ b/actionpack/lib/action_controller/new_base/hide_actions.rb @@ -1,5 +1,7 @@ module ActionController module HideActions + extend ActiveSupport::DependencyModule + included do extlib_inheritable_accessor :hidden_actions self.hidden_actions ||= Set.new diff --git a/actionpack/lib/action_controller/new_base/http.rb b/actionpack/lib/action_controller/new_base/http.rb new file mode 100644 index 0000000000..f269fe70db --- /dev/null +++ b/actionpack/lib/action_controller/new_base/http.rb @@ -0,0 +1,64 @@ +module ActionController + class Http < AbstractController::Base + abstract! + + # :api: public + attr_internal :request, :response, :params + + # :api: public + def self.controller_name + @controller_name ||= controller_path.split("/").last + end + + # :api: public + def controller_name() self.class.controller_name end + + # :api: public + def self.controller_path + @controller_path ||= self.name.sub(/Controller$/, '').underscore + end + + # :api: public + def controller_path() self.class.controller_path end + + # :api: private + def self.internal_methods + ActionController::Http.public_instance_methods(true) + end + + # :api: private + def self.action_names() action_methods end + + # :api: private + def action_names() action_methods end + + # :api: plugin + def self.call(env) + controller = new + controller.call(env).to_rack + end + + # :api: private + def call(name, env) + @_request = ActionDispatch::Request.new(env) + @_response = ActionDispatch::Response.new + @_response.request = request + process(name) + @_response.body = response_body + @_response.prepare! + to_rack + end + + def self.action(name) + @actions ||= {} + @actions[name] ||= proc do |env| + new.call(name, env) + end + end + + # :api: private + def to_rack + @_response.to_a + end + end +end diff --git a/actionpack/lib/action_controller/new_base/layouts.rb b/actionpack/lib/action_controller/new_base/layouts.rb index 89d24fe92d..e851eb5f9a 100644 --- a/actionpack/lib/action_controller/new_base/layouts.rb +++ b/actionpack/lib/action_controller/new_base/layouts.rb @@ -15,7 +15,7 @@ module ActionController # render :text => ..., :layout => ... # or # render :anything_else - if !options.key?(:text) || options.key?(:layout) + if (!options.key?(:text) && !options.key?(:inline)) || options.key?(:layout) options[:_layout] = options.key?(:layout) ? _layout_for_option(options[:layout]) : _default_layout end diff --git a/actionpack/lib/action_controller/new_base/renderer.rb b/actionpack/lib/action_controller/new_base/renderer.rb index be4ea54c3b..41e3dfbe23 100644 --- a/actionpack/lib/action_controller/new_base/renderer.rb +++ b/actionpack/lib/action_controller/new_base/renderer.rb @@ -9,35 +9,30 @@ module ActionController super end - def render(action, options = {}) - # TODO: Move this into #render_to_body - if action.is_a?(Hash) - options, action = action, nil - else - options.merge! :action => action - end - + def render(options = {}) _process_options(options) - self.response_body = render_to_body(options) + super(options) end def render_to_body(options) - unless options.is_a?(Hash) - options = {:action => options} - end - if options.key?(:text) options[:_template] = ActionView::TextTemplate.new(_text(options)) template = nil + elsif options.key?(:inline) + handler = ActionView::Template.handler_class_for_extension(options[:type] || "erb") + template = ActionView::Template.new(options[:inline], "inline #{options[:inline].inspect}", handler, {}) + options[:_template] = template elsif options.key?(:template) options[:_template_name] = options[:template] - elsif options.key?(:action) - options[:_template_name] = options[:action].to_s + else + options[:_template_name] = (options[:action] || action_name).to_s options[:_prefix] = _prefix end - super(options) + ret = super(options) + response.content_type ||= options[:_template].mime_type + ret end private @@ -56,9 +51,9 @@ module ActionController end def _process_options(options) - if status = options[:status] - response.status = status.to_i - end + status, content_type = options.values_at(:status, :content_type) + response.status = status.to_i if status + response.content_type = content_type if content_type end end end diff --git a/actionpack/lib/action_controller/new_base/testing.rb b/actionpack/lib/action_controller/new_base/testing.rb new file mode 100644 index 0000000000..106990b9ba --- /dev/null +++ b/actionpack/lib/action_controller/new_base/testing.rb @@ -0,0 +1,25 @@ +module ActionController + module Testing + + # OMG MEGA HAX + def process_with_test(request, response) + @_request = request + @_response = response + @_response.request = request + ret = process(request.parameters[:action]) + @_response.body = self.response_body + @_response.prepare! + set_test_assigns + ret + end + + def set_test_assigns + @assigns = {} + (instance_variable_names - self.class.protected_instance_variables).each do |var| + name, value = var[1..-1], instance_variable_get(var) + @assigns[name] = value + end + end + + end +end
\ No newline at end of file diff --git a/actionpack/lib/action_controller/routing/route_set.rb b/actionpack/lib/action_controller/routing/route_set.rb index 172b867bf0..45ad8a3a3b 100644 --- a/actionpack/lib/action_controller/routing/route_set.rb +++ b/actionpack/lib/action_controller/routing/route_set.rb @@ -430,7 +430,7 @@ module ActionController def call(env) request = ActionDispatch::Request.new(env) app = Routing::Routes.recognize(request) - app.call(env) + app.action(request.parameters[:action] || 'index').call(env) end def recognize(request) diff --git a/actionpack/lib/action_controller/testing/integration.rb b/actionpack/lib/action_controller/testing/integration.rb index 4f39ee6a01..d6991ab4f5 100644 --- a/actionpack/lib/action_controller/testing/integration.rb +++ b/actionpack/lib/action_controller/testing/integration.rb @@ -309,24 +309,21 @@ module ActionController def self.included(base) base.extend(ClassMethods) base.class_eval do - class << self - alias_method_chain :new, :capture - end + alias_method_chain :initialize, :capture end end + def initialize_with_capture(*args) + initialize_without_capture + self.class.last_instantiation ||= self + end + module ClassMethods #:nodoc: mattr_accessor :last_instantiation def clear_last_instantiation! self.last_instantiation = nil end - - def new_with_capture(*args) - controller = new_without_capture(*args) - self.last_instantiation ||= controller - controller - end end end diff --git a/actionpack/lib/action_controller/testing/process.rb b/actionpack/lib/action_controller/testing/process.rb index 49e8322491..21023ac101 100644 --- a/actionpack/lib/action_controller/testing/process.rb +++ b/actionpack/lib/action_controller/testing/process.rb @@ -131,6 +131,9 @@ module ActionController #:nodoc: @request.session["flash"] = ActionController::Flash::FlashHash.new.update(flash) if flash build_request_uri(action, parameters) + @request.env["action_controller.rescue.request"] = @request + @request.env["action_controller.rescue.response"] = @response + Base.class_eval { include ProcessWithTest } unless Base < ProcessWithTest env = @request.env @@ -139,7 +142,7 @@ module ActionController #:nodoc: # TODO: Enable Lint # app = Rack::Lint.new(app) - status, headers, body = app.call(env) + status, headers, body = app.action(action, env) response = Rack::MockResponse.new(status, headers, body) @response.request, @response.template = @request, @controller.template diff --git a/actionpack/lib/action_controller/testing/process2.rb b/actionpack/lib/action_controller/testing/process2.rb new file mode 100644 index 0000000000..18b7335450 --- /dev/null +++ b/actionpack/lib/action_controller/testing/process2.rb @@ -0,0 +1,69 @@ +require "action_controller/testing/process" + +module ActionController + module TestProcess + + # Executes a request simulating GET HTTP method and set/volley the response + def get(action, parameters = nil, session = nil, flash = nil) + process(action, parameters, session, flash, "GET") + end + + # Executes a request simulating POST HTTP method and set/volley the response + def post(action, parameters = nil, session = nil, flash = nil) + process(action, parameters, session, flash, "POST") + end + + # Executes a request simulating PUT HTTP method and set/volley the response + def put(action, parameters = nil, session = nil, flash = nil) + process(action, parameters, session, flash, "PUT") + end + + # Executes a request simulating DELETE HTTP method and set/volley the response + def delete(action, parameters = nil, session = nil, flash = nil) + process(action, parameters, session, flash, "DELETE") + end + + # Executes a request simulating HEAD HTTP method and set/volley the response + def head(action, parameters = nil, session = nil, flash = nil) + process(action, parameters, session, flash, "HEAD") + end + + def process(action, parameters = nil, session = nil, flash = nil, http_method = 'GET') + # Sanity check for required instance variables so we can give an + # understandable error message. + %w(@controller @request @response).each do |iv_name| + if !(instance_variable_names.include?(iv_name) || instance_variable_names.include?(iv_name.to_sym)) || instance_variable_get(iv_name).nil? + raise "#{iv_name} is nil: make sure you set it in your test's setup method." + end + end + + @request.recycle! + @response.recycle! + @controller.response_body = nil + + @html_document = nil + @request.env['REQUEST_METHOD'] = http_method + + parameters ||= {} + @request.assign_parameters(@controller.class.controller_path, action.to_s, parameters) + + @request.session = ActionController::TestSession.new(session) unless session.nil? + @request.session["flash"] = ActionController::Flash::FlashHash.new.update(flash) if flash + build_request_uri(action, parameters) + @controller.params.merge!(parameters) + # Base.class_eval { include ProcessWithTest } unless Base < ProcessWithTest + @controller.process_with_test(@request, @response) + end + + def build_request_uri(action, parameters) + unless @request.env['REQUEST_URI'] + options = @controller.__send__(:rewrite_options, parameters) + options.update(:only_path => true, :action => action) + + url = ActionController::UrlRewriter.new(@request, parameters) + @request.request_uri = url.rewrite(options) + end + end + + end +end
\ No newline at end of file diff --git a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb index 791254cdf2..71c1e1b9a9 100644 --- a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb +++ b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb @@ -43,6 +43,8 @@ module ActionDispatch def call(env) @app.call(env) rescue Exception => exception + raise exception if env['rack.test'] + log_error(exception) if logger request = Request.new(env) diff --git a/actionpack/lib/action_dispatch/middleware/stack.rb b/actionpack/lib/action_dispatch/middleware/stack.rb index ec8a9ca76e..ade2d6f05e 100644 --- a/actionpack/lib/action_dispatch/middleware/stack.rb +++ b/actionpack/lib/action_dispatch/middleware/stack.rb @@ -34,8 +34,6 @@ module ActionDispatch else @klass.to_s.constantize end - rescue NameError - @klass end def active? diff --git a/actionpack/lib/action_view/paths.rb b/actionpack/lib/action_view/paths.rb index f6d021c92a..95c56faf9c 100644 --- a/actionpack/lib/action_view/paths.rb +++ b/actionpack/lib/action_view/paths.rb @@ -2,7 +2,7 @@ module ActionView #:nodoc: class PathSet < Array #:nodoc: def self.type_cast(obj) if obj.is_a?(String) - cache = !Object.const_defined?(:Rails) || Rails.configuration.cache_classes + cache = !defined?(Rails) || !Rails.respond_to?(:configuration) || Rails.configuration.cache_classes Template::FileSystemPathWithFallback.new(obj, :cache => cache) else obj diff --git a/actionpack/lib/action_view/template/text.rb b/actionpack/lib/action_view/template/text.rb index f81174d707..a777021a12 100644 --- a/actionpack/lib/action_view/template/text.rb +++ b/actionpack/lib/action_view/template/text.rb @@ -1,9 +1,12 @@ module ActionView #:nodoc: class TextTemplate < String #:nodoc: + + def identifier() self end def render(*) self end - def exempt_from_layout?() false end - + def mime_type() Mime::HTML end + + def partial?() false end end end |