aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_controller
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib/action_controller')
-rw-r--r--actionpack/lib/action_controller/abstract.rb1
-rw-r--r--actionpack/lib/action_controller/abstract/base.rb6
-rw-r--r--actionpack/lib/action_controller/abstract/benchmarker.rb28
-rw-r--r--actionpack/lib/action_controller/abstract/callbacks.rb11
-rw-r--r--actionpack/lib/action_controller/abstract/helpers.rb27
-rw-r--r--actionpack/lib/action_controller/abstract/layouts.rb52
-rw-r--r--actionpack/lib/action_controller/abstract/logger.rb1
-rw-r--r--actionpack/lib/action_controller/abstract/renderer.rb24
-rw-r--r--actionpack/lib/action_controller/base/base.rb64
-rw-r--r--actionpack/lib/action_controller/base/chained/benchmarking.rb2
-rw-r--r--actionpack/lib/action_controller/base/chained/filters.rb7
-rw-r--r--actionpack/lib/action_controller/base/chained/flash.rb74
-rw-r--r--actionpack/lib/action_controller/base/filter_parameter_logging.rb97
-rw-r--r--actionpack/lib/action_controller/base/helpers.rb22
-rw-r--r--actionpack/lib/action_controller/base/http_authentication.rb3
-rw-r--r--actionpack/lib/action_controller/base/mime_responds.rb222
-rw-r--r--actionpack/lib/action_controller/base/request_forgery_protection.rb24
-rw-r--r--actionpack/lib/action_controller/base/streaming.rb8
-rw-r--r--actionpack/lib/action_controller/base/verification.rb9
-rw-r--r--actionpack/lib/action_controller/caching.rb30
-rw-r--r--actionpack/lib/action_controller/caching/actions.rb22
-rw-r--r--actionpack/lib/action_controller/dispatch/dispatcher.rb100
-rw-r--r--actionpack/lib/action_controller/dispatch/middlewares.rb2
-rw-r--r--actionpack/lib/action_controller/new_base.rb21
-rw-r--r--actionpack/lib/action_controller/new_base/base.rb51
-rw-r--r--actionpack/lib/action_controller/new_base/compatibility.rb36
-rw-r--r--actionpack/lib/action_controller/new_base/conditional_get.rb2
-rw-r--r--actionpack/lib/action_controller/new_base/helpers.rb130
-rw-r--r--actionpack/lib/action_controller/new_base/http.rb3
-rw-r--r--actionpack/lib/action_controller/new_base/layouts.rb21
-rw-r--r--actionpack/lib/action_controller/new_base/render_options.rb107
-rw-r--r--actionpack/lib/action_controller/new_base/renderer.rb66
-rw-r--r--actionpack/lib/action_controller/new_base/session.rb11
-rw-r--r--actionpack/lib/action_controller/new_base/testing.rb15
-rw-r--r--actionpack/lib/action_controller/new_base/url_for.rb5
-rw-r--r--actionpack/lib/action_controller/testing/integration.rb58
-rw-r--r--actionpack/lib/action_controller/testing/process.rb4
-rw-r--r--actionpack/lib/action_controller/testing/process2.rb5
-rw-r--r--actionpack/lib/action_controller/vendor/html-scanner/html/sanitizer.rb2
39 files changed, 924 insertions, 449 deletions
diff --git a/actionpack/lib/action_controller/abstract.rb b/actionpack/lib/action_controller/abstract.rb
index 48e33282ec..d6b7a44f5f 100644
--- a/actionpack/lib/action_controller/abstract.rb
+++ b/actionpack/lib/action_controller/abstract.rb
@@ -3,6 +3,7 @@ require "active_support/core_ext/module/delegation"
module AbstractController
autoload :Base, "action_controller/abstract/base"
+ autoload :Benchmarker, "action_controller/abstract/benchmarker"
autoload :Callbacks, "action_controller/abstract/callbacks"
autoload :Helpers, "action_controller/abstract/helpers"
autoload :Layouts, "action_controller/abstract/layouts"
diff --git a/actionpack/lib/action_controller/abstract/base.rb b/actionpack/lib/action_controller/abstract/base.rb
index 1f2f096dae..0e4803388a 100644
--- a/actionpack/lib/action_controller/abstract/base.rb
+++ b/actionpack/lib/action_controller/abstract/base.rb
@@ -68,11 +68,11 @@ module AbstractController
self.response_obj = {}
end
- def process(action_name)
- @_action_name = action_name = action_name.to_s
+ def process(action)
+ @_action_name = action_name = action.to_s
unless action_name = method_for_action(action_name)
- raise ActionNotFound, "The action '#{action_name}' could not be found"
+ raise ActionNotFound, "The action '#{action}' could not be found"
end
process_action(action_name)
diff --git a/actionpack/lib/action_controller/abstract/benchmarker.rb b/actionpack/lib/action_controller/abstract/benchmarker.rb
new file mode 100644
index 0000000000..9f5889c704
--- /dev/null
+++ b/actionpack/lib/action_controller/abstract/benchmarker.rb
@@ -0,0 +1,28 @@
+module AbstractController
+ module Benchmarker
+ extend ActiveSupport::DependencyModule
+
+ depends_on Logger
+
+ module ClassMethods
+ def benchmark(title, log_level = ::Logger::DEBUG, use_silence = true)
+ if logger && logger.level >= log_level
+ result = nil
+ ms = Benchmark.ms { result = use_silence ? silence { yield } : yield }
+ logger.add(log_level, "#{title} (#{('%.1f' % ms)}ms)")
+ result
+ else
+ yield
+ end
+ end
+
+ # Silences the logger for the duration of the block.
+ def silence
+ old_logger_level, logger.level = logger.level, ::Logger::ERROR if logger
+ yield
+ ensure
+ logger.level = old_logger_level if logger
+ end
+ 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 51b968c694..e4f9dd3112 100644
--- a/actionpack/lib/action_controller/abstract/callbacks.rb
+++ b/actionpack/lib/action_controller/abstract/callbacks.rb
@@ -36,6 +36,17 @@ module AbstractController
process_action_callback(:#{filter}, name, options)
end
end
+
+ def skip_#{filter}_filter(*names, &blk)
+ options = names.last.is_a?(Hash) ? names.pop : {}
+ _normalize_callback_options(options)
+ names.push(blk) if block_given?
+ names.each do |name|
+ skip_process_action_callback(:#{filter}, name, options)
+ end
+ end
+
+ alias_method :append_#{filter}_filter, :#{filter}_filter
RUBY_EVAL
end
end
diff --git a/actionpack/lib/action_controller/abstract/helpers.rb b/actionpack/lib/action_controller/abstract/helpers.rb
index 968d3080c1..41decfd0c7 100644
--- a/actionpack/lib/action_controller/abstract/helpers.rb
+++ b/actionpack/lib/action_controller/abstract/helpers.rb
@@ -24,11 +24,30 @@ module AbstractController
super
end
-
+
+ # Makes all the (instance) methods in the helper module available to templates rendered through this controller.
+ # See ActionView::Helpers (link:classes/ActionView/Helpers.html) for more about making your own helper modules
+ # available to the templates.
def add_template_helper(mod)
master_helper_module.module_eval { include mod }
end
-
+
+ # Declare a controller method as a helper. For example, the following
+ # makes the +current_user+ controller method available to the view:
+ # class ApplicationController < ActionController::Base
+ # helper_method :current_user, :logged_in?
+ #
+ # def current_user
+ # @current_user ||= User.find_by_id(session[:user])
+ # end
+ #
+ # def logged_in?
+ # current_user != nil
+ # end
+ # end
+ #
+ # In a view:
+ # <% if logged_in? -%>Welcome, <%= current_user.name %><% end -%>
def helper_method(*meths)
meths.flatten.each do |meth|
master_helper_module.class_eval <<-ruby_eval, __FILE__, __LINE__ + 1
@@ -39,14 +58,14 @@ module AbstractController
end
end
- def helper(*args, &blk)
+ def helper(*args, &block)
args.flatten.each do |arg|
case arg
when Module
add_template_helper(arg)
end
end
- master_helper_module.module_eval(&blk) if block_given?
+ master_helper_module.module_eval(&block) if block_given?
end
end
diff --git a/actionpack/lib/action_controller/abstract/layouts.rb b/actionpack/lib/action_controller/abstract/layouts.rb
index 35d5e85ed9..3d6810bda9 100644
--- a/actionpack/lib/action_controller/abstract/layouts.rb
+++ b/actionpack/lib/action_controller/abstract/layouts.rb
@@ -4,11 +4,19 @@ module AbstractController
depends_on Renderer
+ included do
+ extlib_inheritable_accessor :_layout_conditions
+ self._layout_conditions = {}
+ end
+
module ClassMethods
- def layout(layout)
+ def layout(layout, conditions = {})
unless [String, Symbol, FalseClass, NilClass].include?(layout.class)
raise ArgumentError, "Layouts must be specified as a String, Symbol, false, or nil"
end
+
+ conditions.each {|k, v| conditions[k] = Array(v).map {|a| a.to_s} }
+ self._layout_conditions = conditions
@_layout = layout || false # Converts nil to false
_write_layout_method
@@ -31,15 +39,15 @@ module AbstractController
def _write_layout_method
case @_layout
when String
- self.class_eval %{def _layout() #{@_layout.inspect} end}
+ self.class_eval %{def _layout(details) #{@_layout.inspect} end}
when Symbol
- self.class_eval %{def _layout() #{@_layout} end}
+ self.class_eval %{def _layout(details) #{@_layout} end}
when false
- self.class_eval %{def _layout() end}
+ self.class_eval %{def _layout(details) end}
else
self.class_eval %{
- def _layout
- if view_paths.find_by_parts?("#{_implied_layout_name}", {:formats => formats}, "layouts")
+ def _layout(details)
+ if view_paths.find_by_parts?("#{_implied_layout_name}", details, "layouts")
"#{_implied_layout_name}"
else
super
@@ -49,38 +57,50 @@ module AbstractController
end
end
end
-
- def _render_template(template, options)
- _action_view._render_template_from_controller(template, options[:_layout], options, options[:_partial])
- end
private
- def _layout() end # This will be overwritten
+ def _layout(details) end # This will be overwritten
# :api: plugin
# ====
# Override this to mutate the inbound layout name
- def _layout_for_name(name)
+ def _layout_for_name(name, details = {:formats => formats})
unless [String, FalseClass, NilClass].include?(name.class)
raise ArgumentError, "String, false, or nil expected; you passed #{name.inspect}"
end
- name && view_paths.find_by_parts(name, {:formats => formats}, "layouts")
+ name && view_paths.find_by_parts(name, details, _layout_prefix(name))
+ end
+
+ # TODO: Decide if this is the best hook point for the feature
+ def _layout_prefix(name)
+ "layouts"
end
- def _default_layout(require_layout = false)
- if require_layout && !_layout
+ def _default_layout(require_layout = false, details = {:formats => formats})
+ if require_layout && _action_has_layout? && !_layout(details)
raise ArgumentError,
"There was no default layout for #{self.class} in #{view_paths.inspect}"
end
begin
- layout = _layout_for_name(_layout)
+ _layout_for_name(_layout(details), details) if _action_has_layout?
rescue NameError => e
raise NoMethodError,
"You specified #{@_layout.inspect} as the layout, but no such method was found"
end
end
+
+ def _action_has_layout?
+ conditions = _layout_conditions
+ if only = conditions[:only]
+ only.include?(action_name)
+ elsif except = conditions[:except]
+ !except.include?(action_name)
+ else
+ true
+ end
+ end
end
end \ No newline at end of file
diff --git a/actionpack/lib/action_controller/abstract/logger.rb b/actionpack/lib/action_controller/abstract/logger.rb
index 750a5c9fb6..980ede0bed 100644
--- a/actionpack/lib/action_controller/abstract/logger.rb
+++ b/actionpack/lib/action_controller/abstract/logger.rb
@@ -1,4 +1,5 @@
require 'active_support/core_ext/class/attribute_accessors'
+require 'active_support/core_ext/logger'
module AbstractController
module Logger
diff --git a/actionpack/lib/action_controller/abstract/renderer.rb b/actionpack/lib/action_controller/abstract/renderer.rb
index f2044a35ec..d7c68549e1 100644
--- a/actionpack/lib/action_controller/abstract/renderer.rb
+++ b/actionpack/lib/action_controller/abstract/renderer.rb
@@ -33,16 +33,12 @@ module AbstractController
#
# :api: plugin
def render_to_body(options = {})
- name = options[:_template_name] || action_name
-
# TODO: Refactor so we can just use the normal template logic for this
if options[:_partial_object]
_action_view._render_partial_from_controller(options)
- else
- options[:_template] ||= view_paths.find_by_parts(name.to_s, {:formats => formats},
- options[:_prefix], options[:_partial])
-
- _render_template(options[:_template], options)
+ else
+ _determine_template(options)
+ _render_template(options)
end
end
@@ -56,8 +52,8 @@ module AbstractController
AbstractController::Renderer.body_to_s(render_to_body(options))
end
- def _render_template(template, options)
- _action_view._render_template_from_controller(template, nil, options, options[:_partial])
+ def _render_template(options)
+ _action_view._render_template_from_controller(options[:_template], options[:_layout], options, options[:_partial])
end
def view_paths() _view_paths end
@@ -74,6 +70,16 @@ module AbstractController
end
end
+ 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
+
module ClassMethods
def append_view_path(path)
diff --git a/actionpack/lib/action_controller/base/base.rb b/actionpack/lib/action_controller/base/base.rb
index 0993b311cd..1b400d8ed3 100644
--- a/actionpack/lib/action_controller/base/base.rb
+++ b/actionpack/lib/action_controller/base/base.rb
@@ -242,7 +242,6 @@ module ActionController #:nodoc:
# Prepends all the URL-generating helpers from AssetHelper. This makes it possible to easily move javascripts, stylesheets,
# and images to a dedicated asset server away from the main web server. Example:
# ActionController::Base.asset_host = "http://assets.example.com"
- @@asset_host = ""
cattr_accessor :asset_host
# All requests are considered local by default, so everyone will be exposed to detailed debugging screens on errors.
@@ -368,9 +367,8 @@ module ActionController #:nodoc:
attr_reader :template
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
+ request = ActionDispatch::Request.new(env)
+ response = ActionDispatch::Response.new
self.action_name = name && name.to_s
process(request, response).to_a
end
@@ -449,55 +447,6 @@ module ActionController #:nodoc:
@view_paths = superclass.view_paths.dup if @view_paths.nil?
@view_paths.push(*path)
end
-
- # Replace sensitive parameter data from the request log.
- # Filters parameters that have any of the arguments as a substring.
- # Looks in all subhashes of the param hash for keys to filter.
- # If a block is given, each key and value of the parameter hash and all
- # subhashes is passed to it, the value or key
- # can be replaced using String#replace or similar method.
- #
- # Examples:
- # filter_parameter_logging
- # => Does nothing, just slows the logging process down
- #
- # filter_parameter_logging :password
- # => replaces the value to all keys matching /password/i with "[FILTERED]"
- #
- # filter_parameter_logging :foo, "bar"
- # => replaces the value to all keys matching /foo|bar/i with "[FILTERED]"
- #
- # filter_parameter_logging { |k,v| v.reverse! if k =~ /secret/i }
- # => reverses the value to all keys matching /secret/i
- #
- # filter_parameter_logging(:foo, "bar") { |k,v| v.reverse! if k =~ /secret/i }
- # => reverses the value to all keys matching /secret/i, and
- # replaces the value to all keys matching /foo|bar/i with "[FILTERED]"
- def filter_parameter_logging(*filter_words, &block)
- parameter_filter = Regexp.new(filter_words.collect{ |s| s.to_s }.join('|'), true) if filter_words.length > 0
-
- define_method(:filter_parameters) do |unfiltered_parameters|
- filtered_parameters = {}
-
- unfiltered_parameters.each do |key, value|
- if key =~ parameter_filter
- filtered_parameters[key] = '[FILTERED]'
- elsif value.is_a?(Hash)
- filtered_parameters[key] = filter_parameters(value)
- elsif block_given?
- key = key.dup
- value = value.dup if value
- yield key, value
- filtered_parameters[key] = value
- else
- filtered_parameters[key] = value
- end
- end
-
- filtered_parameters
- end
- protected :filter_parameters
- end
@@exempt_from_layout = [ActionView::TemplateHandlers::RJS]
@@ -854,13 +803,6 @@ module ActionController #:nodoc:
logger.info(request_id)
end
- def log_processing_for_parameters
- parameters = respond_to?(:filter_parameters) ? filter_parameters(params) : params.dup
- parameters = parameters.except!(:controller, :action, :format, :_method)
-
- logger.info " Parameters: #{parameters.inspect}" unless parameters.empty?
- end
-
def default_render #:nodoc:
render
end
@@ -934,7 +876,7 @@ module ActionController #:nodoc:
[ Filters, Layout, Renderer, Redirector, Responder, Benchmarking, Rescue, Flash, MimeResponds, Helpers,
Cookies, Caching, Verification, Streaming, SessionManagement,
HttpAuthentication::Basic::ControllerMethods, HttpAuthentication::Digest::ControllerMethods, RecordIdentifier,
- RequestForgeryProtection, Translation
+ RequestForgeryProtection, Translation, FilterParameterLogging
].each do |mod|
include mod
end
diff --git a/actionpack/lib/action_controller/base/chained/benchmarking.rb b/actionpack/lib/action_controller/base/chained/benchmarking.rb
index 66e9e9c31d..57a1ac8314 100644
--- a/actionpack/lib/action_controller/base/chained/benchmarking.rb
+++ b/actionpack/lib/action_controller/base/chained/benchmarking.rb
@@ -21,7 +21,7 @@ module ActionController #:nodoc:
# easy to include benchmarking statements in production software that will remain inexpensive because the benchmark
# will only be conducted if the log level is low enough.
def benchmark(title, log_level = Logger::DEBUG, use_silence = true)
- if logger && logger.level == log_level
+ if logger && logger.level >= log_level
result = nil
ms = Benchmark.ms { result = use_silence ? silence { yield } : yield }
logger.add(log_level, "#{title} (#{('%.1f' % ms)}ms)")
diff --git a/actionpack/lib/action_controller/base/chained/filters.rb b/actionpack/lib/action_controller/base/chained/filters.rb
index 98fe306fd5..e121c0129d 100644
--- a/actionpack/lib/action_controller/base/chained/filters.rb
+++ b/actionpack/lib/action_controller/base/chained/filters.rb
@@ -571,12 +571,7 @@ module ActionController #:nodoc:
# Returns an array of Filter objects for this controller.
def filter_chain
- if chain = read_inheritable_attribute('filter_chain')
- return chain
- else
- write_inheritable_attribute('filter_chain', FilterChain.new)
- return filter_chain
- end
+ read_inheritable_attribute('filter_chain') || write_inheritable_attribute('filter_chain', FilterChain.new)
end
# Returns all the before filters for this class and all its ancestors.
diff --git a/actionpack/lib/action_controller/base/chained/flash.rb b/actionpack/lib/action_controller/base/chained/flash.rb
index 56ee9c67e2..6bd482d85a 100644
--- a/actionpack/lib/action_controller/base/chained/flash.rb
+++ b/actionpack/lib/action_controller/base/chained/flash.rb
@@ -26,9 +26,18 @@ module ActionController #:nodoc:
#
# See docs on the FlashHash class for more details about the flash.
module Flash
- def self.included(base)
- base.class_eval do
- include InstanceMethods
+ extend ActiveSupport::DependencyModule
+
+ # TODO : Remove the defined? check when new base is the main base
+ depends_on Session if defined?(ActionController::Http)
+
+ included do
+ # TODO : Remove the defined? check when new base is the main base
+ if defined?(ActionController::Http)
+ include InstanceMethodsForNewBase
+ else
+ include InstanceMethodsForBase
+
alias_method_chain :perform_action, :flash
alias_method_chain :reset_session, :flash
end
@@ -135,29 +144,50 @@ module ActionController #:nodoc:
end
end
- module InstanceMethods #:nodoc:
+ module InstanceMethodsForBase #:nodoc:
protected
- def perform_action_with_flash
- perform_action_without_flash
- remove_instance_variable(:@_flash) if defined? @_flash
- end
- def reset_session_with_flash
- reset_session_without_flash
- remove_instance_variable(:@_flash) if defined? @_flash
- end
+ def perform_action_with_flash
+ perform_action_without_flash
+ remove_instance_variable(:@_flash) if defined?(@_flash)
+ end
- # Access the contents of the flash. Use <tt>flash["notice"]</tt> to
- # read a notice you put there or <tt>flash["notice"] = "hello"</tt>
- # to put a new one.
- def flash #:doc:
- unless defined? @_flash
- @_flash = session["flash"] ||= FlashHash.new
- @_flash.sweep
- end
+ def reset_session_with_flash
+ reset_session_without_flash
+ remove_instance_variable(:@_flash) if defined?(@_flash)
+ end
+ end
- @_flash
- end
+ module InstanceMethodsForNewBase #:nodoc:
+ protected
+
+ def reset_session
+ super
+ remove_flash_instance_variable
+ end
+
+ def process_action(method_name)
+ super
+ remove_flash_instance_variable
+ end
+
+ def remove_flash_instance_variable
+ remove_instance_variable(:@_flash) if defined?(@_flash)
+ end
+ end
+
+ protected
+
+ # Access the contents of the flash. Use <tt>flash["notice"]</tt> to
+ # read a notice you put there or <tt>flash["notice"] = "hello"</tt>
+ # to put a new one.
+ def flash #:doc:
+ unless defined?(@_flash)
+ @_flash = session["flash"] ||= FlashHash.new
+ @_flash.sweep
+ end
+
+ @_flash
end
end
end
diff --git a/actionpack/lib/action_controller/base/filter_parameter_logging.rb b/actionpack/lib/action_controller/base/filter_parameter_logging.rb
new file mode 100644
index 0000000000..f5a678ca03
--- /dev/null
+++ b/actionpack/lib/action_controller/base/filter_parameter_logging.rb
@@ -0,0 +1,97 @@
+module ActionController
+ module FilterParameterLogging
+ extend ActiveSupport::DependencyModule
+
+ # TODO : Remove the defined? check when new base is the main base
+ if defined?(ActionController::Http)
+ depends_on AbstractController::Logger
+ end
+
+ included do
+ if defined?(ActionController::Http)
+ include InstanceMethodsForNewBase
+ end
+ end
+
+ module ClassMethods
+ # Replace sensitive parameter data from the request log.
+ # Filters parameters that have any of the arguments as a substring.
+ # Looks in all subhashes of the param hash for keys to filter.
+ # If a block is given, each key and value of the parameter hash and all
+ # subhashes is passed to it, the value or key
+ # can be replaced using String#replace or similar method.
+ #
+ # Examples:
+ # filter_parameter_logging
+ # => Does nothing, just slows the logging process down
+ #
+ # filter_parameter_logging :password
+ # => replaces the value to all keys matching /password/i with "[FILTERED]"
+ #
+ # filter_parameter_logging :foo, "bar"
+ # => replaces the value to all keys matching /foo|bar/i with "[FILTERED]"
+ #
+ # filter_parameter_logging { |k,v| v.reverse! if k =~ /secret/i }
+ # => reverses the value to all keys matching /secret/i
+ #
+ # filter_parameter_logging(:foo, "bar") { |k,v| v.reverse! if k =~ /secret/i }
+ # => reverses the value to all keys matching /secret/i, and
+ # replaces the value to all keys matching /foo|bar/i with "[FILTERED]"
+ def filter_parameter_logging(*filter_words, &block)
+ parameter_filter = Regexp.new(filter_words.collect{ |s| s.to_s }.join('|'), true) if filter_words.length > 0
+
+ define_method(:filter_parameters) do |unfiltered_parameters|
+ filtered_parameters = {}
+
+ unfiltered_parameters.each do |key, value|
+ if key =~ parameter_filter
+ filtered_parameters[key] = '[FILTERED]'
+ elsif value.is_a?(Hash)
+ filtered_parameters[key] = filter_parameters(value)
+ elsif block_given?
+ key = key.dup
+ value = value.dup if value
+ yield key, value
+ filtered_parameters[key] = value
+ else
+ filtered_parameters[key] = value
+ end
+ end
+
+ filtered_parameters
+ end
+ protected :filter_parameters
+ end
+ end
+
+ module InstanceMethodsForNewBase
+ # TODO : Fix the order of information inside such that it's exactly same as the old base
+ def process(*)
+ ret = super
+
+ if logger
+ parameters = respond_to?(:filter_parameters) ? filter_parameters(params) : params.dup
+ parameters = parameters.except!(:controller, :action, :format, :_method, :only_path)
+
+ unless parameters.empty?
+ # TODO : Move DelayedLog to AS
+ log = AbstractController::Logger::DelayedLog.new { " Parameters: #{parameters.inspect}" }
+ logger.info(log)
+ end
+ end
+
+ ret
+ end
+ end
+
+ private
+
+ # TODO : This method is not needed for the new base
+ def log_processing_for_parameters
+ parameters = respond_to?(:filter_parameters) ? filter_parameters(params) : params.dup
+ parameters = parameters.except!(:controller, :action, :format, :_method)
+
+ logger.info " Parameters: #{parameters.inspect}" unless parameters.empty?
+ end
+ end
+end
diff --git a/actionpack/lib/action_controller/base/helpers.rb b/actionpack/lib/action_controller/base/helpers.rb
index ba65032f6a..96fa7896a9 100644
--- a/actionpack/lib/action_controller/base/helpers.rb
+++ b/actionpack/lib/action_controller/base/helpers.rb
@@ -3,23 +3,19 @@ require 'active_support/dependencies'
# FIXME: helper { ... } is broken on Ruby 1.9
module ActionController #:nodoc:
module Helpers #:nodoc:
- def self.included(base)
+ extend ActiveSupport::DependencyModule
+
+ included do
# Initialize the base module to aggregate its helpers.
- base.class_inheritable_accessor :master_helper_module
- base.master_helper_module = Module.new
+ class_inheritable_accessor :master_helper_module
+ self.master_helper_module = Module.new
# Set the default directory for helpers
- base.class_inheritable_accessor :helpers_dir
- base.helpers_dir = (defined?(RAILS_ROOT) ? "#{RAILS_ROOT}/app/helpers" : "app/helpers")
-
- # Extend base with class methods to declare helpers.
- base.extend(ClassMethods)
+ class_inheritable_accessor :helpers_dir
+ self.helpers_dir = (defined?(RAILS_ROOT) ? "#{RAILS_ROOT}/app/helpers" : "app/helpers")
- base.class_eval do
- # Wrap inherited to create a new master helper module for subclasses.
- class << self
- alias_method_chain :inherited, :helper
- end
+ class << self
+ alias_method_chain :inherited, :helper
end
end
diff --git a/actionpack/lib/action_controller/base/http_authentication.rb b/actionpack/lib/action_controller/base/http_authentication.rb
index 0be53cb02d..680900446c 100644
--- a/actionpack/lib/action_controller/base/http_authentication.rb
+++ b/actionpack/lib/action_controller/base/http_authentication.rb
@@ -194,9 +194,10 @@ module ActionController
if valid_nonce && realm == credentials[:realm] && opaque == credentials[:opaque]
password = password_procedure.call(credentials[:username])
+ method = request.env['rack.methodoverride.original_method'] || request.env['REQUEST_METHOD']
[true, false].any? do |password_is_ha1|
- expected = expected_response(request.env['REQUEST_METHOD'], request.env['REQUEST_URI'], credentials, password, password_is_ha1)
+ expected = expected_response(method, request.env['REQUEST_URI'], credentials, password, password_is_ha1)
expected == credentials[:response]
end
end
diff --git a/actionpack/lib/action_controller/base/mime_responds.rb b/actionpack/lib/action_controller/base/mime_responds.rb
index 9ec8883f8e..3c17dda1a1 100644
--- a/actionpack/lib/action_controller/base/mime_responds.rb
+++ b/actionpack/lib/action_controller/base/mime_responds.rb
@@ -1,123 +1,103 @@
module ActionController #:nodoc:
module MimeResponds #:nodoc:
- def self.included(base)
- base.module_eval do
- include ActionController::MimeResponds::InstanceMethods
- end
- end
-
- module InstanceMethods
- # Without web-service support, an action which collects the data for displaying a list of people
- # might look something like this:
- #
- # def index
- # @people = Person.find(:all)
- # end
- #
- # Here's the same action, with web-service support baked in:
- #
- # def index
- # @people = Person.find(:all)
- #
- # respond_to do |format|
- # format.html
- # format.xml { render :xml => @people.to_xml }
- # end
- # end
- #
- # What that says is, "if the client wants HTML in response to this action, just respond as we
- # would have before, but if the client wants XML, return them the list of people in XML format."
- # (Rails determines the desired response format from the HTTP Accept header submitted by the client.)
- #
- # Supposing you have an action that adds a new person, optionally creating their company
- # (by name) if it does not already exist, without web-services, it might look like this:
- #
- # def create
- # @company = Company.find_or_create_by_name(params[:company][:name])
- # @person = @company.people.create(params[:person])
- #
- # redirect_to(person_list_url)
- # end
- #
- # Here's the same action, with web-service support baked in:
- #
- # def create
- # company = params[:person].delete(:company)
- # @company = Company.find_or_create_by_name(company[:name])
- # @person = @company.people.create(params[:person])
- #
- # respond_to do |format|
- # format.html { redirect_to(person_list_url) }
- # format.js
- # format.xml { render :xml => @person.to_xml(:include => @company) }
- # end
- # end
- #
- # If the client wants HTML, we just redirect them back to the person list. If they want Javascript
- # (format.js), then it is an RJS request and we render the RJS template associated with this action.
- # Lastly, if the client wants XML, we render the created person as XML, but with a twist: we also
- # include the person's company in the rendered XML, so you get something like this:
- #
- # <person>
- # <id>...</id>
- # ...
- # <company>
- # <id>...</id>
- # <name>...</name>
- # ...
- # </company>
- # </person>
- #
- # Note, however, the extra bit at the top of that action:
- #
- # company = params[:person].delete(:company)
- # @company = Company.find_or_create_by_name(company[:name])
- #
- # This is because the incoming XML document (if a web-service request is in process) can only contain a
- # single root-node. So, we have to rearrange things so that the request looks like this (url-encoded):
- #
- # person[name]=...&person[company][name]=...&...
- #
- # And, like this (xml-encoded):
- #
- # <person>
- # <name>...</name>
- # <company>
- # <name>...</name>
- # </company>
- # </person>
- #
- # In other words, we make the request so that it operates on a single entity's person. Then, in the action,
- # we extract the company data from the request, find or create the company, and then create the new person
- # with the remaining data.
- #
- # Note that you can define your own XML parameter parser which would allow you to describe multiple entities
- # in a single request (i.e., by wrapping them all in a single root node), but if you just go with the flow
- # and accept Rails' defaults, life will be much easier.
- #
- # Further more, you may call the #any method on the block's object in order to run the same code for different responses.
- # def index
- #
- # respond_to do |format|
- # format.html { @people = People.all(:limit => 10) }
- # format.any(:xml, :atom) { @people = People.all }
- # end
- # end
- #
- # This will limit the @people variable to 10 people records if we're requesting HTML, but will list all the
- # people for any xml or atom request.
- #
- # If you need to use a MIME type which isn't supported by default, you can register your own handlers in
- # environment.rb as follows.
- #
- # Mime::Type.register "image/jpg", :jpg
- def respond_to(*types, &block)
- raise ArgumentError, "respond_to takes either types or a block, never both" unless types.any? ^ block
- block ||= lambda { |responder| types.each { |type| responder.send(type) } }
- responder = Responder.new(self)
- block.call(responder)
- responder.respond
- end
+ # Without web-service support, an action which collects the data for displaying a list of people
+ # might look something like this:
+ #
+ # def index
+ # @people = Person.find(:all)
+ # end
+ #
+ # Here's the same action, with web-service support baked in:
+ #
+ # def index
+ # @people = Person.find(:all)
+ #
+ # respond_to do |format|
+ # format.html
+ # format.xml { render :xml => @people.to_xml }
+ # end
+ # end
+ #
+ # What that says is, "if the client wants HTML in response to this action, just respond as we
+ # would have before, but if the client wants XML, return them the list of people in XML format."
+ # (Rails determines the desired response format from the HTTP Accept header submitted by the client.)
+ #
+ # Supposing you have an action that adds a new person, optionally creating their company
+ # (by name) if it does not already exist, without web-services, it might look like this:
+ #
+ # def create
+ # @company = Company.find_or_create_by_name(params[:company][:name])
+ # @person = @company.people.create(params[:person])
+ #
+ # redirect_to(person_list_url)
+ # end
+ #
+ # Here's the same action, with web-service support baked in:
+ #
+ # def create
+ # company = params[:person].delete(:company)
+ # @company = Company.find_or_create_by_name(company[:name])
+ # @person = @company.people.create(params[:person])
+ #
+ # respond_to do |format|
+ # format.html { redirect_to(person_list_url) }
+ # format.js
+ # format.xml { render :xml => @person.to_xml(:include => @company) }
+ # end
+ # end
+ #
+ # If the client wants HTML, we just redirect them back to the person list. If they want Javascript
+ # (format.js), then it is an RJS request and we render the RJS template associated with this action.
+ # Lastly, if the client wants XML, we render the created person as XML, but with a twist: we also
+ # include the person's company in the rendered XML, so you get something like this:
+ #
+ # <person>
+ # <id>...</id>
+ # ...
+ # <company>
+ # <id>...</id>
+ # <name>...</name>
+ # ...
+ # </company>
+ # </person>
+ #
+ # Note, however, the extra bit at the top of that action:
+ #
+ # company = params[:person].delete(:company)
+ # @company = Company.find_or_create_by_name(company[:name])
+ #
+ # This is because the incoming XML document (if a web-service request is in process) can only contain a
+ # single root-node. So, we have to rearrange things so that the request looks like this (url-encoded):
+ #
+ # person[name]=...&person[company][name]=...&...
+ #
+ # And, like this (xml-encoded):
+ #
+ # <person>
+ # <name>...</name>
+ # <company>
+ # <name>...</name>
+ # </company>
+ # </person>
+ #
+ # In other words, we make the request so that it operates on a single entity's person. Then, in the action,
+ # we extract the company data from the request, find or create the company, and then create the new person
+ # with the remaining data.
+ #
+ # Note that you can define your own XML parameter parser which would allow you to describe multiple entities
+ # in a single request (i.e., by wrapping them all in a single root node), but if you just go with the flow
+ # and accept Rails' defaults, life will be much easier.
+ #
+ # If you need to use a MIME type which isn't supported by default, you can register your own handlers in
+ # environment.rb as follows.
+ #
+ # Mime::Type.register "image/jpg", :jpg
+ def respond_to(*types, &block)
+ raise ArgumentError, "respond_to takes either types or a block, never both" unless types.any? ^ block
+ block ||= lambda { |responder| types.each { |type| responder.send(type) } }
+ responder = Responder.new(self)
+ block.call(responder)
+ responder.respond
end
class Responder #:nodoc:
@@ -139,8 +119,14 @@ module ActionController #:nodoc:
@order << mime_type
@responses[mime_type] ||= Proc.new do
+ # TODO: Remove this when new base is merged in
+ if defined?(Http)
+ @controller.formats = [mime_type.to_sym]
+ end
+
@controller.template.formats = [mime_type.to_sym]
@response.content_type = mime_type.to_s
+
block_given? ? block.call : @controller.send(:render, :action => @controller.action_name)
end
end
diff --git a/actionpack/lib/action_controller/base/request_forgery_protection.rb b/actionpack/lib/action_controller/base/request_forgery_protection.rb
index df91dc1006..f30a4d41a3 100644
--- a/actionpack/lib/action_controller/base/request_forgery_protection.rb
+++ b/actionpack/lib/action_controller/base/request_forgery_protection.rb
@@ -3,12 +3,26 @@ module ActionController #:nodoc:
end
module RequestForgeryProtection
- def self.included(base)
- base.class_eval do
- helper_method :form_authenticity_token
- helper_method :protect_against_forgery?
+ extend ActiveSupport::DependencyModule
+
+ # TODO : Remove the defined? check when new base is the main base
+ if defined?(ActionController::Http)
+ depends_on AbstractController::Helpers, Session
+ end
+
+ included do
+ if defined?(ActionController::Http)
+ # Sets the token parameter name for RequestForgery. Calling +protect_from_forgery+
+ # sets it to <tt>:authenticity_token</tt> by default.
+ cattr_accessor :request_forgery_protection_token
+
+ # Controls whether request forgergy protection is turned on or not. Turned off by default only in test mode.
+ class_inheritable_accessor :allow_forgery_protection
+ self.allow_forgery_protection = true
end
- base.extend(ClassMethods)
+
+ helper_method :form_authenticity_token
+ helper_method :protect_against_forgery?
end
# Protecting controller actions from CSRF attacks by ensuring that all forms are coming from the current web application, not a
diff --git a/actionpack/lib/action_controller/base/streaming.rb b/actionpack/lib/action_controller/base/streaming.rb
index 9f80f48c3d..5872ba99a2 100644
--- a/actionpack/lib/action_controller/base/streaming.rb
+++ b/actionpack/lib/action_controller/base/streaming.rb
@@ -2,6 +2,13 @@ module ActionController #:nodoc:
# Methods for sending arbitrary data and for streaming files to the browser,
# instead of rendering.
module Streaming
+ extend ActiveSupport::DependencyModule
+
+ # TODO : Remove the defined? check when new base is the main base
+ if defined?(ActionController::Http)
+ depends_on ActionController::Renderer
+ end
+
DEFAULT_SEND_FILE_OPTIONS = {
:type => 'application/octet-stream'.freeze,
:disposition => 'attachment'.freeze,
@@ -88,6 +95,7 @@ module ActionController #:nodoc:
head options[:status], X_SENDFILE_HEADER => path
else
if options[:stream]
+ # TODO : Make render :text => proc {} work with the new base
render :status => options[:status], :text => Proc.new { |response, output|
logger.info "Streaming file #{path}" unless logger.nil?
len = options[:buffer_size] || 4096
diff --git a/actionpack/lib/action_controller/base/verification.rb b/actionpack/lib/action_controller/base/verification.rb
index c62b81b666..3fa5a105b1 100644
--- a/actionpack/lib/action_controller/base/verification.rb
+++ b/actionpack/lib/action_controller/base/verification.rb
@@ -1,7 +1,10 @@
module ActionController #:nodoc:
module Verification #:nodoc:
- def self.included(base) #:nodoc:
- base.extend(ClassMethods)
+ extend ActiveSupport::DependencyModule
+
+ # TODO : Remove the defined? check when new base is the main base
+ if defined?(ActionController::Http)
+ depends_on AbstractController::Callbacks, Session, Flash, Renderer
end
# This module provides a class-level method for specifying that certain
@@ -102,7 +105,7 @@ module ActionController #:nodoc:
end
def verify_presence_of_keys_in_hash_flash_or_params(options) # :nodoc:
- [*options[:params] ].find { |v| params[v].nil? } ||
+ [*options[:params] ].find { |v| v && params[v.to_sym].nil? } ||
[*options[:session]].find { |v| session[v].nil? } ||
[*options[:flash] ].find { |v| flash[v].nil? }
end
diff --git a/actionpack/lib/action_controller/caching.rb b/actionpack/lib/action_controller/caching.rb
index ffd8081edc..2f2eec10f6 100644
--- a/actionpack/lib/action_controller/caching.rb
+++ b/actionpack/lib/action_controller/caching.rb
@@ -24,31 +24,31 @@ module ActionController #:nodoc:
# ActionController::Base.cache_store = :mem_cache_store, "localhost"
# ActionController::Base.cache_store = MyOwnStore.new("parameter")
module Caching
+ extend ActiveSupport::DependencyModule
+
autoload :Actions, 'action_controller/caching/actions'
autoload :Fragments, 'action_controller/caching/fragments'
autoload :Pages, 'action_controller/caching/pages'
autoload :Sweeper, 'action_controller/caching/sweeping'
autoload :Sweeping, 'action_controller/caching/sweeping'
- def self.included(base) #:nodoc:
- base.class_eval do
- @@cache_store = nil
- cattr_reader :cache_store
+ included do
+ @@cache_store = nil
+ cattr_reader :cache_store
- # Defines the storage option for cached fragments
- def self.cache_store=(store_option)
- @@cache_store = ActiveSupport::Cache.lookup_store(store_option)
- end
+ # Defines the storage option for cached fragments
+ def self.cache_store=(store_option)
+ @@cache_store = ActiveSupport::Cache.lookup_store(store_option)
+ end
- include Pages, Actions, Fragments
- include Sweeping if defined?(ActiveRecord)
+ include Pages, Actions, Fragments
+ include Sweeping if defined?(ActiveRecord)
- @@perform_caching = true
- cattr_accessor :perform_caching
+ @@perform_caching = true
+ cattr_accessor :perform_caching
- def self.cache_configured?
- perform_caching && cache_store
- end
+ def self.cache_configured?
+ perform_caching && cache_store
end
end
diff --git a/actionpack/lib/action_controller/caching/actions.rb b/actionpack/lib/action_controller/caching/actions.rb
index 2b822b52c8..430db3932f 100644
--- a/actionpack/lib/action_controller/caching/actions.rb
+++ b/actionpack/lib/action_controller/caching/actions.rb
@@ -61,8 +61,14 @@ module ActionController #:nodoc:
filter_options = { :only => actions, :if => options.delete(:if), :unless => options.delete(:unless) }
cache_filter = ActionCacheFilter.new(:layout => options.delete(:layout), :cache_path => options.delete(:cache_path), :store_options => options)
- around_filter(filter_options) do |controller, action|
- cache_filter.filter(controller, action)
+
+ # TODO: Remove this once new base is swapped in.
+ if defined?(Http)
+ around_filter cache_filter, filter_options
+ else
+ around_filter(filter_options) do |controller, action|
+ cache_filter.filter(controller, action)
+ end
end
end
end
@@ -85,14 +91,22 @@ module ActionController #:nodoc:
@options = options
end
+ # TODO: Remove once New Base is merged
def filter(controller, action)
should_continue = before(controller)
action.call if should_continue
after(controller)
end
+ def around_process_action(controller)
+ should_continue = before(controller)
+ yield if should_continue
+ after(controller)
+ end
+
def before(controller)
cache_path = ActionCachePath.new(controller, path_options_for(controller, @options.slice(:cache_path)))
+
if cache = controller.read_fragment(cache_path.path, @options[:store_options])
controller.rendered_action_cache = true
set_content_type!(controller, cache_path.extension)
@@ -129,7 +143,9 @@ module ActionController #:nodoc:
end
def content_for_layout(controller)
- controller.template.layout && controller.template.instance_variable_get('@cached_content_for_layout')
+ # TODO: Remove this when new base is merged in
+ template = controller.respond_to?(:template) ? controller.template : controller._action_view
+ template.layout && template.instance_variable_get('@cached_content_for_layout')
end
end
diff --git a/actionpack/lib/action_controller/dispatch/dispatcher.rb b/actionpack/lib/action_controller/dispatch/dispatcher.rb
index 63866caed9..9ad1cadfd3 100644
--- a/actionpack/lib/action_controller/dispatch/dispatcher.rb
+++ b/actionpack/lib/action_controller/dispatch/dispatcher.rb
@@ -1,87 +1,65 @@
+require 'active_support/core_ext/module/delegation'
+
module ActionController
# Dispatches requests to the appropriate controller and takes care of
# reloading the app after each request when Dependencies.load? is true.
class Dispatcher
+ cattr_accessor :prepare_each_request
+ self.prepare_each_request = false
+
+ cattr_accessor :router
+ self.router = Routing::Routes
+
+ cattr_accessor :middleware
+ self.middleware = ActionDispatch::MiddlewareStack.new do |middleware|
+ middlewares = File.join(File.dirname(__FILE__), "middlewares.rb")
+ middleware.instance_eval(File.read(middlewares), middlewares, 1)
+ end
+
class << self
def define_dispatcher_callbacks(cache_classes)
unless cache_classes
+ # Run prepare callbacks before every request in development mode
+ self.prepare_each_request = true
+
# Development mode callbacks
- before_dispatch :reload_application
- after_dispatch :cleanup_application
+ ActionDispatch::Callbacks.before_dispatch do |app|
+ ActionController::Dispatcher.router.reload
+ end
+
+ ActionDispatch::Callbacks.after_dispatch do
+ # Cleanup the application before processing the current request.
+ ActiveRecord::Base.reset_subclasses if defined?(ActiveRecord)
+ ActiveSupport::Dependencies.clear
+ ActiveRecord::Base.clear_reloadable_connections! if defined?(ActiveRecord)
+ end
ActionView::Helpers::AssetTagHelper.cache_asset_timestamps = false
end
if defined?(ActiveRecord)
- to_prepare(:activerecord_instantiate_observers) { ActiveRecord::Base.instantiate_observers }
+ to_prepare(:activerecord_instantiate_observers) do
+ ActiveRecord::Base.instantiate_observers
+ end
end
- after_dispatch :flush_logger if Base.logger && Base.logger.respond_to?(:flush)
+ if Base.logger && Base.logger.respond_to?(:flush)
+ after_dispatch do
+ Base.logger.flush
+ end
+ end
to_prepare do
I18n.reload!
end
end
- # Add a preparation callback. Preparation callbacks are run before every
- # request in development mode, and before the first request in production
- # mode.
- #
- # An optional identifier may be supplied for the callback. If provided,
- # to_prepare may be called again with the same identifier to replace the
- # existing callback. Passing an identifier is a suggested practice if the
- # code adding a preparation block may be reloaded.
- def to_prepare(identifier = nil, &block)
- @prepare_dispatch_callbacks ||= ActiveSupport::Callbacks::CallbackChain.new
- callback = ActiveSupport::Callbacks::Callback.new(:prepare_dispatch, block, :identifier => identifier)
- @prepare_dispatch_callbacks.replace_or_append!(callback)
- end
+ delegate :to_prepare, :prepare_dispatch, :before_dispatch, :after_dispatch,
+ :to => ActionDispatch::Callbacks
- def run_prepare_callbacks
- new.send :run_callbacks, :prepare_dispatch
+ def new
+ @@middleware.build(@@router)
end
end
-
- cattr_accessor :router
- self.router = Routing::Routes
-
- cattr_accessor :middleware
- self.middleware = ActionDispatch::MiddlewareStack.new do |middleware|
- middlewares = File.join(File.dirname(__FILE__), "middlewares.rb")
- middleware.instance_eval(File.read(middlewares), middlewares, 1)
- end
-
- include ActiveSupport::Callbacks
- define_callbacks :prepare_dispatch, :before_dispatch, :after_dispatch
-
- def initialize
- @app = @@middleware.build(@@router)
- freeze
- end
-
- def call(env)
- run_callbacks :before_dispatch
- @app.call(env)
- ensure
- run_callbacks :after_dispatch, :enumerator => :reverse_each
- end
-
- def reload_application
- # Run prepare callbacks before every request in development mode
- run_callbacks :prepare_dispatch
-
- @@router.reload
- end
-
- def cleanup_application
- # Cleanup the application before processing the current request.
- ActiveRecord::Base.reset_subclasses if defined?(ActiveRecord)
- ActiveSupport::Dependencies.clear
- ActiveRecord::Base.clear_reloadable_connections! if defined?(ActiveRecord)
- end
-
- def flush_logger
- Base.logger.flush
- end
end
end
diff --git a/actionpack/lib/action_controller/dispatch/middlewares.rb b/actionpack/lib/action_controller/dispatch/middlewares.rb
index 0e4ab6fa39..b25ed3fd3f 100644
--- a/actionpack/lib/action_controller/dispatch/middlewares.rb
+++ b/actionpack/lib/action_controller/dispatch/middlewares.rb
@@ -2,8 +2,8 @@ use "Rack::Lock", :if => lambda {
!ActionController::Base.allow_concurrency
}
-use "ActionDispatch::Failsafe"
use "ActionDispatch::ShowExceptions", lambda { ActionController::Base.consider_all_requests_local }
+use "ActionDispatch::Callbacks", lambda { ActionController::Dispatcher.prepare_each_request }
use "ActionDispatch::Rescue", lambda {
controller = (::ApplicationController rescue ActionController::Base)
# TODO: Replace with controller.action(:_rescue_action)
diff --git a/actionpack/lib/action_controller/new_base.rb b/actionpack/lib/action_controller/new_base.rb
index bc47713529..276be50614 100644
--- a/actionpack/lib/action_controller/new_base.rb
+++ b/actionpack/lib/action_controller/new_base.rb
@@ -7,13 +7,19 @@ module ActionController
autoload :Rails2Compatibility, "action_controller/new_base/compatibility"
autoload :Redirector, "action_controller/new_base/redirector"
autoload :Renderer, "action_controller/new_base/renderer"
+ autoload :RenderOptions, "action_controller/new_base/render_options"
+ autoload :Renderers, "action_controller/new_base/render_options"
autoload :Rescue, "action_controller/new_base/rescuable"
autoload :Testing, "action_controller/new_base/testing"
autoload :UrlFor, "action_controller/new_base/url_for"
-
+ autoload :Session, "action_controller/new_base/session"
+ autoload :Helpers, "action_controller/new_base/helpers"
+
# Ported modules
# require 'action_controller/routing'
+ autoload :Caching, 'action_controller/caching'
autoload :Dispatcher, 'action_controller/dispatch/dispatcher'
+ autoload :MimeResponds, 'action_controller/base/mime_responds'
autoload :PolymorphicRoutes, 'action_controller/routing/generation/polymorphic_routes'
autoload :RecordIdentifier, 'action_controller/record_identifier'
autoload :Resources, 'action_controller/routing/resources'
@@ -21,9 +27,18 @@ module ActionController
autoload :TestCase, 'action_controller/testing/test_case'
autoload :UrlRewriter, 'action_controller/routing/generation/url_rewriter'
autoload :UrlWriter, 'action_controller/routing/generation/url_rewriter'
-
+
+ autoload :Verification, 'action_controller/base/verification'
+ autoload :Flash, 'action_controller/base/chained/flash'
+ autoload :RequestForgeryProtection, 'action_controller/base/request_forgery_protection'
+ autoload :Streaming, 'action_controller/base/streaming'
+ autoload :HttpAuthentication, 'action_controller/base/http_authentication'
+ autoload :FilterParameterLogging, 'action_controller/base/filter_parameter_logging'
+ autoload :Translation, 'action_controller/translation'
+ autoload :Cookies, 'action_controller/base/cookies'
+
require 'action_controller/routing'
end
require 'action_dispatch'
-require 'action_view' \ No newline at end of file
+require 'action_view'
diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb
index c25ffd5c84..ffe608ade4 100644
--- a/actionpack/lib/action_controller/new_base/base.rb
+++ b/actionpack/lib/action_controller/new_base/base.rb
@@ -2,41 +2,56 @@ module ActionController
class Base < Http
abstract!
+ include AbstractController::Benchmarker
include AbstractController::Callbacks
- include AbstractController::Helpers
include AbstractController::Logger
-
+
+ include ActionController::Helpers
include ActionController::HideActions
include ActionController::UrlFor
include ActionController::Redirector
include ActionController::Renderer
+ include ActionController::Renderers::All
include ActionController::Layouts
include ActionController::ConditionalGet
# Legacy modules
include SessionManagement
include ActionDispatch::StatusCodes
+ 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 process_action(method_name)
ret = super
- render if response_body.nil?
+ default_render if response_body.nil?
ret
end
- def _implicit_render
+ def default_render
render
end
def method_for_action(action_name)
super || begin
if view_paths.find_by_parts?(action_name.to_s, {:formats => formats, :locales => [I18n.locale]}, controller_path)
- "_implicit_render"
+ "default_render"
end
end
end
@@ -61,7 +76,7 @@ module ActionController
end
end
- def render_to_body(action = nil, options = {})
+ 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)
@@ -78,11 +93,25 @@ module ActionController
if options.key?(:action) && options[:action].to_s.index("/")
options[:template] = options.delete(:action)
end
-
- # options = {:template => options.to_s} if options.is_a?(String) || options.is_a?(Symbol)
- super(options) || " "
+
+ if options[:status]
+ options[:status] = interpret_status(options[:status]).to_i
+ end
+
+ options[:update] = blk if block_given?
+ options
end
-
+
+ def render(action = nil, options = {}, &blk)
+ options = _normalize_options(action, options, &blk)
+ super(options)
+ end
+
+ def render_to_string(action = nil, options = {}, &blk)
+ options = _normalize_options(action, options, &blk)
+ super(options)
+ end
+
# 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+.
@@ -140,4 +169,4 @@ module ActionController
super(url, status)
end
end
-end \ No newline at end of file
+end
diff --git a/actionpack/lib/action_controller/new_base/compatibility.rb b/actionpack/lib/action_controller/new_base/compatibility.rb
index 0a283887b6..b3190486e8 100644
--- a/actionpack/lib/action_controller/new_base/compatibility.rb
+++ b/actionpack/lib/action_controller/new_base/compatibility.rb
@@ -1,7 +1,10 @@
module ActionController
module Rails2Compatibility
extend ActiveSupport::DependencyModule
-
+
+ class ::ActionController::ActionControllerError < StandardError #:nodoc:
+ end
+
# Temporary hax
included do
::ActionController::UnknownAction = ::AbstractController::ActionNotFound
@@ -53,10 +56,23 @@ module ActionController
cattr_accessor :consider_all_requests_local
self.consider_all_requests_local = true
+
+ # Prepends all the URL-generating helpers from AssetHelper. This makes it possible to easily move javascripts, stylesheets,
+ # and images to a dedicated asset server away from the main web server. Example:
+ # ActionController::Base.asset_host = "http://assets.example.com"
+ cattr_accessor :asset_host
end
+ # For old tests
+ def initialize_template_class(*) end
+ def assign_shortcuts(*) end
+
+ # TODO: Remove this after we flip
+ def template
+ _action_view
+ end
+
module ClassMethods
- def protect_from_forgery() end
def consider_all_requests_local() end
def rescue_action(env)
raise env["action_dispatch.rescue.exception"]
@@ -80,7 +96,9 @@ module ActionController
options[:text] = nil if options[:nothing] == true
- super
+ body = super
+ body = [' '] if body.blank?
+ body
end
def _handle_method_missing
@@ -91,10 +109,12 @@ module ActionController
super || (respond_to?(:method_missing) && "_handle_method_missing")
end
- def _layout_for_name(name)
- name &&= name.sub(%r{^/?layouts/}, '')
- super
+ def _layout_prefix(name)
+ super unless name =~ /\blayouts/
+ end
+
+ def performed?
+ response_body
end
-
end
-end \ No newline at end of file
+end
diff --git a/actionpack/lib/action_controller/new_base/conditional_get.rb b/actionpack/lib/action_controller/new_base/conditional_get.rb
index e1407e671a..116ce34494 100644
--- a/actionpack/lib/action_controller/new_base/conditional_get.rb
+++ b/actionpack/lib/action_controller/new_base/conditional_get.rb
@@ -57,7 +57,7 @@ module ActionController
raise ArgumentError, "too few arguments to head"
end
options = args.extract_options!
- status = interpret_status(args.shift || options.delete(:status) || :ok)
+ 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
diff --git a/actionpack/lib/action_controller/new_base/helpers.rb b/actionpack/lib/action_controller/new_base/helpers.rb
new file mode 100644
index 0000000000..e00c3c338b
--- /dev/null
+++ b/actionpack/lib/action_controller/new_base/helpers.rb
@@ -0,0 +1,130 @@
+require 'active_support/core_ext/load_error'
+require 'active_support/core_ext/name_error'
+require 'active_support/dependencies'
+
+module ActionController
+ module Helpers
+ extend ActiveSupport::DependencyModule
+
+ depends_on AbstractController::Helpers
+
+ included do
+ # Set the default directory for helpers
+ class_inheritable_accessor :helpers_dir
+ self.helpers_dir = (defined?(RAILS_ROOT) ? "#{RAILS_ROOT}/app/helpers" : "app/helpers")
+ end
+
+ module ClassMethods
+ def inherited(klass)
+ klass.__send__ :default_helper_module!
+ super
+ end
+
+ # The +helper+ class method can take a series of helper module names, a block, or both.
+ #
+ # * <tt>*args</tt>: One or more modules, strings or symbols, or the special symbol <tt>:all</tt>.
+ # * <tt>&block</tt>: A block defining helper methods.
+ #
+ # ==== Examples
+ # When the argument is a string or symbol, the method will provide the "_helper" suffix, require the file
+ # and include the module in the template class. The second form illustrates how to include custom helpers
+ # when working with namespaced controllers, or other cases where the file containing the helper definition is not
+ # in one of Rails' standard load paths:
+ # helper :foo # => requires 'foo_helper' and includes FooHelper
+ # helper 'resources/foo' # => requires 'resources/foo_helper' and includes Resources::FooHelper
+ #
+ # When the argument is a module it will be included directly in the template class.
+ # helper FooHelper # => includes FooHelper
+ #
+ # When the argument is the symbol <tt>:all</tt>, the controller will include all helpers beneath
+ # <tt>ActionController::Base.helpers_dir</tt> (defaults to <tt>app/helpers/**/*.rb</tt> under RAILS_ROOT).
+ # helper :all
+ #
+ # Additionally, the +helper+ class method can receive and evaluate a block, making the methods defined available
+ # to the template.
+ # # One line
+ # helper { def hello() "Hello, world!" end }
+ # # Multi-line
+ # helper do
+ # def foo(bar)
+ # "#{bar} is the very best"
+ # end
+ # end
+ #
+ # Finally, all the above styles can be mixed together, and the +helper+ method can be invoked with a mix of
+ # +symbols+, +strings+, +modules+ and blocks.
+ # helper(:three, BlindHelper) { def mice() 'mice' end }
+ #
+ def helper(*args, &block)
+ args.flatten.each do |arg|
+ case arg
+ when :all
+ helper all_application_helpers
+ when String, Symbol
+ file_name = arg.to_s.underscore + '_helper'
+ class_name = file_name.camelize
+
+ begin
+ require_dependency(file_name)
+ rescue LoadError => load_error
+ requiree = / -- (.*?)(\.rb)?$/.match(load_error.message).to_a[1]
+ if requiree == file_name
+ msg = "Missing helper file helpers/#{file_name}.rb"
+ raise LoadError.new(msg).copy_blame!(load_error)
+ else
+ raise
+ end
+ end
+
+ super class_name.constantize
+ else
+ super args
+ end
+ end
+
+ # Evaluate block in template class if given.
+ master_helper_module.module_eval(&block) if block_given?
+ end
+
+ # Declares helper accessors for controller attributes. For example, the
+ # following adds new +name+ and <tt>name=</tt> instance methods to a
+ # controller and makes them available to the view:
+ # helper_attr :name
+ # attr_accessor :name
+ def helper_attr(*attrs)
+ attrs.flatten.each { |attr| helper_method(attr, "#{attr}=") }
+ end
+
+ # Provides a proxy to access helpers methods from outside the view.
+ def helpers
+ unless @helper_proxy
+ @helper_proxy = ActionView::Base.new
+ @helper_proxy.extend master_helper_module
+ else
+ @helper_proxy
+ end
+ end
+
+ private
+
+ def default_helper_module!
+ unless name.blank?
+ module_name = name.sub(/Controller$|$/, 'Helper')
+ module_path = module_name.split('::').map { |m| m.underscore }.join('/')
+ require_dependency module_path
+ helper module_name.constantize
+ end
+ rescue MissingSourceFile => e
+ raise unless e.is_missing? module_path
+ rescue NameError => e
+ raise unless e.missing_name? module_name
+ end
+
+ # Extract helper names from files in app/helpers/**/*.rb
+ def all_application_helpers
+ extract = /^#{Regexp.quote(helpers_dir)}\/?(.*)_helper.rb$/
+ Dir["#{helpers_dir}/**/*_helper.rb"].map { |file| file.sub extract, '\1' }
+ end
+ end # ClassMethods
+ end
+end
diff --git a/actionpack/lib/action_controller/new_base/http.rb b/actionpack/lib/action_controller/new_base/http.rb
index 8891a2a8c3..2525e221a6 100644
--- a/actionpack/lib/action_controller/new_base/http.rb
+++ b/actionpack/lib/action_controller/new_base/http.rb
@@ -37,7 +37,7 @@ module ActionController
end
delegate :headers, :to => "@_response"
-
+
def params
@_params ||= @_request.parameters
end
@@ -60,7 +60,6 @@ module ActionController
# :api: private
def to_rack
- @_response.body = response_body
@_response.prepare!
@_response.to_a
end
diff --git a/actionpack/lib/action_controller/new_base/layouts.rb b/actionpack/lib/action_controller/new_base/layouts.rb
index bf5b14c4e1..35068db770 100644
--- a/actionpack/lib/action_controller/new_base/layouts.rb
+++ b/actionpack/lib/action_controller/new_base/layouts.rb
@@ -11,23 +11,20 @@ module ActionController
end
end
- def render_to_body(options)
- # render :text => ..., :layout => ...
- # or
- # render :anything_else
+ private
+
+ def _determine_template(options)
+ super
if (!options.key?(:text) && !options.key?(:inline) && !options.key?(:partial)) || options.key?(:layout)
- options[:_layout] = options.key?(:layout) ? _layout_for_option(options[:layout]) : _default_layout
+ options[:_layout] = _layout_for_option(options.key?(:layout) ? options[:layout] : :none, options[:_template].details)
end
-
- super
end
-
- private
- def _layout_for_option(name)
+ def _layout_for_option(name, details)
case name
- when String then _layout_for_name(name)
- when true then _default_layout(true)
+ when String then _layout_for_name(name, details)
+ when true then _default_layout(true, details)
+ when :none then _default_layout(false, details)
when false, nil then nil
else
raise ArgumentError,
diff --git a/actionpack/lib/action_controller/new_base/render_options.rb b/actionpack/lib/action_controller/new_base/render_options.rb
new file mode 100644
index 0000000000..581a92cb7b
--- /dev/null
+++ b/actionpack/lib/action_controller/new_base/render_options.rb
@@ -0,0 +1,107 @@
+module ActionController
+ module RenderOptions
+ extend ActiveSupport::DependencyModule
+
+ included do
+ extlib_inheritable_accessor :_renderers
+ self._renderers = []
+ end
+
+ module ClassMethods
+ def _write_render_options
+ renderers = _renderers.map do |r|
+ <<-RUBY_EVAL
+ if options.key?(:#{r})
+ _process_options(options)
+ return _render_#{r}(options[:#{r}], options)
+ end
+ RUBY_EVAL
+ end
+
+ class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
+ def _handle_render_options(options)
+ #{renderers.join}
+ end
+ RUBY_EVAL
+ end
+
+ def _add_render_option(name)
+ _renderers << name
+ _write_render_options
+ end
+ end
+
+ def render_to_body(options)
+ _handle_render_options(options) || super
+ end
+ end
+
+ module RenderOption
+ extend ActiveSupport::DependencyModule
+
+ included do
+ extend ActiveSupport::DependencyModule
+ depends_on ::ActionController::RenderOptions
+
+ def self.register_renderer(name)
+ included { _add_render_option(name) }
+ end
+ end
+ end
+
+ module Renderers
+ module Json
+ include RenderOption
+ register_renderer :json
+
+ def _render_json(json, options)
+ json = ActiveSupport::JSON.encode(json) unless json.respond_to?(:to_str)
+ json = "#{options[:callback]}(#{json})" unless options[:callback].blank?
+ response.content_type ||= Mime::JSON
+ self.response_body = json
+ end
+ end
+
+ module Js
+ include RenderOption
+ register_renderer :js
+
+ def _render_js(js, options)
+ response.content_type ||= Mime::JS
+ self.response_body = js
+ end
+ end
+
+ module Xml
+ include RenderOption
+ register_renderer :xml
+
+ def _render_xml(xml, options)
+ response.content_type ||= Mime::XML
+ self.response_body = xml.respond_to?(:to_xml) ? xml.to_xml : xml
+ end
+ end
+
+ module Rjs
+ include RenderOption
+ register_renderer :update
+
+ def _render_update(proc, options)
+ generator = ActionView::Helpers::PrototypeHelper::JavaScriptGenerator.new(_action_view, &proc)
+ response.content_type = Mime::JS
+ self.response_body = generator.to_s
+ end
+ end
+
+ module All
+ extend ActiveSupport::DependencyModule
+
+ included do
+ include ::ActionController::Renderers::Json
+ include ::ActionController::Renderers::Js
+ include ::ActionController::Renderers::Xml
+ include ::ActionController::Renderers::Rjs
+ end
+ end
+ end
+end
diff --git a/actionpack/lib/action_controller/new_base/renderer.rb b/actionpack/lib/action_controller/new_base/renderer.rb
index 8a9f230603..987751a601 100644
--- a/actionpack/lib/action_controller/new_base/renderer.rb
+++ b/actionpack/lib/action_controller/new_base/renderer.rb
@@ -4,17 +4,45 @@ module ActionController
depends_on AbstractController::Renderer
- def initialize(*)
- self.formats = [:html]
+ def process_action(*)
+ self.formats = request.formats.map {|x| x.to_sym}
super
end
+ def response_body=(body)
+ response.body = body if response
+ super
+ end
+
+ def render(options)
+ super
+ options[:_template] ||= _action_view._partial
+ response.content_type ||= begin
+ mime = options[:_template].mime_type
+ formats.include?(mime && mime.to_sym) || formats.include?(:all) ? mime : Mime::Type.lookup_by_extension(formats.first)
+ end
+ response_body
+ end
+
def render_to_body(options)
_process_options(options)
+ if options.key?(:partial)
+ _render_partial(options[:partial], options)
+ end
+
+ super
+ end
+
+ private
+
+ def _prefix
+ controller_path
+ end
+
+ def _determine_template(options)
if options.key?(:text)
- options[:_template] = ActionView::TextTemplate.new(_text(options))
- template = nil
+ options[:_template] = ActionView::TextTemplate.new(options[:text], formats.first)
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, {})
@@ -23,35 +51,14 @@ module ActionController
options[:_template_name] = options[:template]
elsif options.key?(:file)
options[:_template_name] = options[:file]
- elsif options.key?(:partial)
- _render_partial(options[:partial], options)
- else
+ elsif !options.key?(:partial)
options[:_template_name] = (options[:action] || action_name).to_s
options[:_prefix] = _prefix
end
- ret = super(options)
-
- options[:_template] ||= _action_view._partial
- response.content_type ||= options[:_template].mime_type
- ret
+ super
end
-
- private
-
- def _prefix
- controller_path
- end
-
- def _text(options)
- text = options[:text]
- case text
- when nil then " "
- else text.to_s
- end
- end
-
def _render_partial(partial, options)
case partial
when true
@@ -68,9 +75,10 @@ module ActionController
end
def _process_options(options)
- status, content_type = options.values_at(:status, :content_type)
- response.status = status.to_i if status
+ status, content_type, location = options.values_at(:status, :content_type, :location)
+ response.status = status if status
response.content_type = content_type if content_type
+ response.headers["Location"] = url_for(location) if location
end
end
end
diff --git a/actionpack/lib/action_controller/new_base/session.rb b/actionpack/lib/action_controller/new_base/session.rb
new file mode 100644
index 0000000000..a8715555fb
--- /dev/null
+++ b/actionpack/lib/action_controller/new_base/session.rb
@@ -0,0 +1,11 @@
+module ActionController
+ module Session
+ def session
+ @_request.session
+ end
+
+ def reset_session
+ @_request.reset_session
+ end
+ end
+end
diff --git a/actionpack/lib/action_controller/new_base/testing.rb b/actionpack/lib/action_controller/new_base/testing.rb
index b39d8d539d..d8c3421587 100644
--- a/actionpack/lib/action_controller/new_base/testing.rb
+++ b/actionpack/lib/action_controller/new_base/testing.rb
@@ -1,13 +1,13 @@
module ActionController
module Testing
-
+
# OMG MEGA HAX
- def process_with_test(request, response)
+ def process_with_new_base_test(request, response)
@_request = request
@_response = response
@_response.request = request
ret = process(request.parameters[:action])
- @_response.body = self.response_body || " "
+ @_response.body ||= self.response_body
@_response.prepare!
set_test_assigns
ret
@@ -20,6 +20,11 @@ module ActionController
@assigns[name] = value
end
end
-
+
+ # TODO : Rewrite tests using controller.headers= to use Rack env
+ def headers=(new_headers)
+ @_response ||= ActionDispatch::Response.new
+ @_response.headers.replace(new_headers)
+ end
end
-end \ No newline at end of file
+end
diff --git a/actionpack/lib/action_controller/new_base/url_for.rb b/actionpack/lib/action_controller/new_base/url_for.rb
index af5b21012b..94de9fab50 100644
--- a/actionpack/lib/action_controller/new_base/url_for.rb
+++ b/actionpack/lib/action_controller/new_base/url_for.rb
@@ -1,5 +1,10 @@
module ActionController
module UrlFor
+ def process_action(*)
+ initialize_current_url
+ super
+ end
+
def initialize_current_url
@url = UrlRewriter.new(request, params.clone)
end
diff --git a/actionpack/lib/action_controller/testing/integration.rb b/actionpack/lib/action_controller/testing/integration.rb
index d6991ab4f5..cc157816e2 100644
--- a/actionpack/lib/action_controller/testing/integration.rb
+++ b/actionpack/lib/action_controller/testing/integration.rb
@@ -2,6 +2,9 @@ require 'stringio'
require 'uri'
require 'active_support/test_case'
+require 'rack/mock_session'
+require 'rack/test/cookie_jar'
+
module ActionController
module Integration #:nodoc:
module RequestHelpers
@@ -62,8 +65,8 @@ module ActionController
# with 'HTTP_' if not already.
def xml_http_request(request_method, path, parameters = nil, headers = nil)
headers ||= {}
- headers['X-Requested-With'] = 'XMLHttpRequest'
- headers['Accept'] ||= [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ')
+ headers['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
+ headers['HTTP_ACCEPT'] ||= [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ')
process(request_method, path, parameters, headers)
end
alias xhr :xml_http_request
@@ -121,6 +124,8 @@ module ActionController
# IntegrationTest#open_session, rather than instantiating
# Integration::Session directly.
class Session
+ DEFAULT_HOST = "www.example.com"
+
include Test::Unit::Assertions
include ActionDispatch::Assertions
include ActionController::TestProcess
@@ -145,7 +150,9 @@ module ActionController
# A map of the cookies returned by the last response, and which will be
# sent with the next request.
- attr_reader :cookies
+ def cookies
+ @mock_session.cookie_jar
+ end
# A reference to the controller instance used by the last request.
attr_reader :controller
@@ -172,11 +179,11 @@ module ActionController
# session.reset!
def reset!
@https = false
- @cookies = {}
+ @mock_session = Rack::MockSession.new(@app, DEFAULT_HOST)
@controller = @request = @response = nil
@request_count = 0
- self.host = "www.example.com"
+ self.host = DEFAULT_HOST
self.remote_addr = "127.0.0.1"
self.accept = "text/xml,application/xml,application/xhtml+xml," +
"text/html;q=0.9,text/plain;q=0.8,image/png," +
@@ -227,8 +234,9 @@ module ActionController
end
private
+
# Performs the actual request.
- def process(method, path, parameters = nil, headers = nil)
+ def process(method, path, parameters = nil, rack_environment = nil)
if path =~ %r{://}
location = URI.parse(path)
https! URI::HTTPS === location if location.scheme
@@ -242,8 +250,6 @@ module ActionController
end
end
- ActionController::Base.clear_last_instantiation!
-
opts = {
:method => method,
:params => parameters,
@@ -258,34 +264,23 @@ module ActionController
"HTTP_HOST" => host,
"REMOTE_ADDR" => remote_addr,
"CONTENT_TYPE" => "application/x-www-form-urlencoded",
- "HTTP_ACCEPT" => accept,
- "HTTP_COOKIE" => cookies.inject("") { |string, (name, value)|
- string << "#{name}=#{value}; "
- }
+ "HTTP_ACCEPT" => accept
}
env = Rack::MockRequest.env_for(path, opts)
- (headers || {}).each do |key, value|
- key = key.to_s.upcase.gsub(/-/, "_")
- key = "HTTP_#{key}" unless env.has_key?(key) || key =~ /^HTTP_/
+ (rack_environment || {}).each do |key, value|
env[key] = value
end
- app = Rack::Lint.new(@app)
- status, headers, body = app.call(env)
- mock_response = ::Rack::MockResponse.new(status, headers, body)
+ @controller = ActionController::Base.capture_instantiation do
+ @mock_session.request(URI.parse(path), env)
+ end
@request_count += 1
@request = ActionDispatch::Request.new(env)
- @response = ActionDispatch::TestResponse.from_response(mock_response)
-
- @cookies.merge!(@response.cookies)
+ @response = ActionDispatch::TestResponse.from_response(@mock_session.last_response)
@html_document = nil
- if @controller = ActionController::Base.last_instantiation
- @controller.send(:set_test_assigns)
- end
-
return response.status
end
@@ -306,11 +301,10 @@ module ActionController
# A module used to extend ActionController::Base, so that integration tests
# can capture the controller used to satisfy a request.
module ControllerCapture #:nodoc:
- def self.included(base)
- base.extend(ClassMethods)
- base.class_eval do
- alias_method_chain :initialize, :capture
- end
+ extend ActiveSupport::DependencyModule
+
+ included do
+ alias_method_chain :initialize, :capture
end
def initialize_with_capture(*args)
@@ -321,8 +315,10 @@ module ActionController
module ClassMethods #:nodoc:
mattr_accessor :last_instantiation
- def clear_last_instantiation!
+ def capture_instantiation
self.last_instantiation = nil
+ yield
+ return last_instantiation
end
end
end
diff --git a/actionpack/lib/action_controller/testing/process.rb b/actionpack/lib/action_controller/testing/process.rb
index 8f4358c33e..9647f8ce45 100644
--- a/actionpack/lib/action_controller/testing/process.rb
+++ b/actionpack/lib/action_controller/testing/process.rb
@@ -41,6 +41,7 @@ module ActionController #:nodoc:
end
def recycle!
+ @formats = nil
@env.delete_if { |k, v| k =~ /^(action_dispatch|rack)\.request/ }
@env.delete_if { |k, v| k =~ /^action_dispatch\.rescue/ }
@env['action_dispatch.request.query_parameters'] = {}
@@ -132,9 +133,6 @@ 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
diff --git a/actionpack/lib/action_controller/testing/process2.rb b/actionpack/lib/action_controller/testing/process2.rb
index e9a79369b9..677dd41781 100644
--- a/actionpack/lib/action_controller/testing/process2.rb
+++ b/actionpack/lib/action_controller/testing/process2.rb
@@ -40,6 +40,8 @@ module ActionController
@request.recycle!
@response.recycle!
@controller.response_body = nil
+ @controller.formats = nil
+ @controller.params = nil
@html_document = nil
@request.env['REQUEST_METHOD'] = http_method
@@ -53,7 +55,8 @@ module ActionController
@controller.request = @request
@controller.params.merge!(parameters)
# Base.class_eval { include ProcessWithTest } unless Base < ProcessWithTest
- @controller.process_with_test(@request, @response)
+ @controller.process_with_new_base_test(@request, @response)
+ @response
end
def build_request_uri(action, parameters)
diff --git a/actionpack/lib/action_controller/vendor/html-scanner/html/sanitizer.rb b/actionpack/lib/action_controller/vendor/html-scanner/html/sanitizer.rb
index ae20f9947c..a992f7d912 100644
--- a/actionpack/lib/action_controller/vendor/html-scanner/html/sanitizer.rb
+++ b/actionpack/lib/action_controller/vendor/html-scanner/html/sanitizer.rb
@@ -73,7 +73,7 @@ module HTML
# Specifies the default Set of tags that the #sanitize helper will allow unscathed.
self.allowed_tags = Set.new(%w(strong em b i p code pre tt samp kbd var sub
- sup dfn cite big small address hr br div span h1 h2 h3 h4 h5 h6 ul ol li dt dd abbr
+ sup dfn cite big small address hr br div span h1 h2 h3 h4 h5 h6 ul ol li dl dt dd abbr
acronym a img blockquote del ins))
# Specifies the default Set of html attributes that the #sanitize helper will leave