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/base.rb34
-rw-r--r--actionpack/lib/action_controller/caching.rb37
-rw-r--r--actionpack/lib/action_controller/caching/fragments.rb4
-rw-r--r--actionpack/lib/action_controller/caching/pages.rb48
-rw-r--r--actionpack/lib/action_controller/caching/sweeping.rb4
-rw-r--r--actionpack/lib/action_controller/deprecated.rb2
-rw-r--r--actionpack/lib/action_controller/deprecated/base.rb131
-rw-r--r--actionpack/lib/action_controller/metal.rb43
-rw-r--r--actionpack/lib/action_controller/metal/compatibility.rb98
-rw-r--r--actionpack/lib/action_controller/metal/configuration.rb28
-rw-r--r--actionpack/lib/action_controller/metal/head.rb1
-rw-r--r--actionpack/lib/action_controller/metal/helpers.rb4
-rw-r--r--actionpack/lib/action_controller/metal/hide_actions.rb10
-rw-r--r--actionpack/lib/action_controller/metal/http_authentication.rb50
-rw-r--r--actionpack/lib/action_controller/metal/implicit_render.rb21
-rw-r--r--actionpack/lib/action_controller/metal/instrumentation.rb2
-rw-r--r--actionpack/lib/action_controller/metal/rack_delegation.rb5
-rw-r--r--actionpack/lib/action_controller/metal/redirecting.rb1
-rw-r--r--actionpack/lib/action_controller/metal/renderers.rb2
-rw-r--r--actionpack/lib/action_controller/metal/rendering.rb68
-rw-r--r--actionpack/lib/action_controller/metal/request_forgery_protection.rb45
-rw-r--r--actionpack/lib/action_controller/metal/session_management.rb36
-rw-r--r--actionpack/lib/action_controller/metal/streaming.rb67
-rw-r--r--actionpack/lib/action_controller/metal/testing.rb1
-rw-r--r--actionpack/lib/action_controller/metal/url_for.rb167
-rw-r--r--actionpack/lib/action_controller/middleware.rb3
-rw-r--r--actionpack/lib/action_controller/polymorphic_routes.rb3
-rw-r--r--actionpack/lib/action_controller/railtie.rb70
-rw-r--r--actionpack/lib/action_controller/railties/log_subscriber.rb (renamed from actionpack/lib/action_controller/railties/subscriber.rb)12
-rw-r--r--actionpack/lib/action_controller/railties/url_helpers.rb14
-rw-r--r--actionpack/lib/action_controller/record_identifier.rb21
-rw-r--r--actionpack/lib/action_controller/test_case.rb31
-rw-r--r--actionpack/lib/action_controller/url_rewriter.rb76
33 files changed, 485 insertions, 654 deletions
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb
index 10244f8216..fcd3cb9bd3 100644
--- a/actionpack/lib/action_controller/base.rb
+++ b/actionpack/lib/action_controller/base.rb
@@ -15,7 +15,6 @@ module ActionController
include ActionController::Renderers::All
include ActionController::ConditionalGet
include ActionController::RackDelegation
- include ActionController::Configuration
# Legacy modules
include SessionManagement
@@ -30,35 +29,13 @@ module ActionController
include ActionController::Verification
include ActionController::RequestForgeryProtection
include ActionController::Streaming
+ include ActionController::RecordIdentifier
include ActionController::HttpAuthentication::Basic::ControllerMethods
include ActionController::HttpAuthentication::Digest::ControllerMethods
# Add instrumentations hooks at the bottom, to ensure they instrument
# all the methods properly.
include ActionController::Instrumentation
-
- # TODO: Extract into its own module
- # This should be moved together with other normalizing behavior
- module ImplicitRender
- def send_action(*)
- ret = super
- default_render unless response_body
- ret
- end
-
- def default_render
- render
- end
-
- def method_for_action(action_name)
- super || begin
- if template_exists?(action_name.to_s, {:formats => formats}, :_prefix => controller_path)
- "default_render"
- end
- end
- end
- end
-
include ImplicitRender
include ActionController::Rescue
@@ -82,12 +59,9 @@ module ActionController
filter
end
- protected
+ ActionController.run_base_hooks(self)
- # Overwrite url rewriter to use request.
- def _url_rewriter
- return ActionController::UrlRewriter unless request
- @_url_rewriter ||= ActionController::UrlRewriter.new(request, params)
- end
end
end
+
+require "action_controller/deprecated/base"
diff --git a/actionpack/lib/action_controller/caching.rb b/actionpack/lib/action_controller/caching.rb
index d784138ebe..b3fa129929 100644
--- a/actionpack/lib/action_controller/caching.rb
+++ b/actionpack/lib/action_controller/caching.rb
@@ -40,28 +40,34 @@ module ActionController #:nodoc:
autoload :Sweeping, 'action_controller/caching/sweeping'
end
- 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)
+ module ConfigMethods
+ def cache_store
+ config.cache_store
end
- include Pages, Actions, Fragments
- include Sweeping if defined?(ActiveRecord)
+ def cache_store=(store)
+ config.cache_store = ActiveSupport::Cache.lookup_store(store)
+ end
- @@perform_caching = true
- cattr_accessor :perform_caching
- end
+ private
- module ClassMethods
def cache_configured?
perform_caching && cache_store
end
end
+ include ConfigMethods
+ include Pages, Actions, Fragments
+ include Sweeping if defined?(ActiveRecord)
+
+ included do
+ extend ConfigMethods
+
+ @@perform_caching = true
+ cattr_accessor :perform_caching
+ end
+
+
def caching_allowed?
request.get? && response.status == 200
end
@@ -75,10 +81,5 @@ module ActionController #:nodoc:
yield
end
end
-
- private
- def cache_configured?
- self.class.cache_configured?
- end
end
end
diff --git a/actionpack/lib/action_controller/caching/fragments.rb b/actionpack/lib/action_controller/caching/fragments.rb
index 00a7f034d3..bb5ff95a67 100644
--- a/actionpack/lib/action_controller/caching/fragments.rb
+++ b/actionpack/lib/action_controller/caching/fragments.rb
@@ -41,7 +41,9 @@ module ActionController #:nodoc:
else
pos = buffer.length
block.call
- write_fragment(name, buffer[pos..-1], options)
+ content = buffer[pos..-1]
+ content = content.as_str if content.respond_to?(:as_str)
+ write_fragment(name, content, options)
end
else
block.call
diff --git a/actionpack/lib/action_controller/caching/pages.rb b/actionpack/lib/action_controller/caching/pages.rb
index 5797eeebd6..fe95f0e0d7 100644
--- a/actionpack/lib/action_controller/caching/pages.rb
+++ b/actionpack/lib/action_controller/caching/pages.rb
@@ -1,5 +1,6 @@
require 'fileutils'
require 'uri'
+require 'active_support/core_ext/class/attribute_accessors'
module ActionController #:nodoc:
module Caching
@@ -34,27 +35,26 @@ module ActionController #:nodoc:
# Additionally, you can expire caches using Sweepers that act on changes in the model to determine when a cache is supposed to be
# expired.
module Pages
- def self.included(base) #:nodoc:
- base.extend(ClassMethods)
- base.class_eval do
- @@page_cache_directory = defined?(Rails.public_path) ? Rails.public_path : ""
- ##
- # :singleton-method:
- # The cache directory should be the document root for the web server and is set using <tt>Base.page_cache_directory = "/document/root"</tt>.
- # For Rails, this directory has already been set to Rails.public_path (which is usually set to <tt>RAILS_ROOT + "/public"</tt>). Changing
- # this setting can be useful to avoid naming conflicts with files in <tt>public/</tt>, but doing so will likely require configuring your
- # web server to look in the new location for cached files.
- cattr_accessor :page_cache_directory
-
- @@page_cache_extension = '.html'
- ##
- # :singleton-method:
- # Most Rails requests do not have an extension, such as <tt>/weblog/new</tt>. In these cases, the page caching mechanism will add one in
- # order to make it easy for the cached files to be picked up properly by the web server. By default, this cache extension is <tt>.html</tt>.
- # If you want something else, like <tt>.php</tt> or <tt>.shtml</tt>, just set Base.page_cache_extension. In cases where a request already has an
- # extension, such as <tt>.xml</tt> or <tt>.rss</tt>, page caching will not add an extension. This allows it to work well with RESTful apps.
- cattr_accessor :page_cache_extension
- end
+ extend ActiveSupport::Concern
+
+ included do
+ @@page_cache_directory = defined?(Rails.public_path) ? Rails.public_path : ""
+ ##
+ # :singleton-method:
+ # The cache directory should be the document root for the web server and is set using <tt>Base.page_cache_directory = "/document/root"</tt>.
+ # For Rails, this directory has already been set to Rails.public_path (which is usually set to <tt>RAILS_ROOT + "/public"</tt>). Changing
+ # this setting can be useful to avoid naming conflicts with files in <tt>public/</tt>, but doing so will likely require configuring your
+ # web server to look in the new location for cached files.
+ cattr_accessor :page_cache_directory
+
+ @@page_cache_extension = '.html'
+ ##
+ # :singleton-method:
+ # Most Rails requests do not have an extension, such as <tt>/weblog/new</tt>. In these cases, the page caching mechanism will add one in
+ # order to make it easy for the cached files to be picked up properly by the web server. By default, this cache extension is <tt>.html</tt>.
+ # If you want something else, like <tt>.php</tt> or <tt>.shtml</tt>, just set Base.page_cache_extension. In cases where a request already has an
+ # extension, such as <tt>.xml</tt> or <tt>.rss</tt>, page caching will not add an extension. This allows it to work well with RESTful apps.
+ cattr_accessor :page_cache_extension
end
module ClassMethods
@@ -121,10 +121,10 @@ module ActionController #:nodoc:
if options.is_a?(Hash)
if options[:action].is_a?(Array)
options[:action].dup.each do |action|
- self.class.expire_page(url_for(options.merge(:only_path => true, :skip_relative_url_root => true, :action => action)))
+ self.class.expire_page(url_for(options.merge(:only_path => true, :action => action)))
end
else
- self.class.expire_page(url_for(options.merge(:only_path => true, :skip_relative_url_root => true)))
+ self.class.expire_page(url_for(options.merge(:only_path => true)))
end
else
self.class.expire_page(options)
@@ -139,7 +139,7 @@ module ActionController #:nodoc:
path = case options
when Hash
- url_for(options.merge(:only_path => true, :skip_relative_url_root => true, :format => params[:format]))
+ url_for(options.merge(:only_path => true, :format => params[:format]))
when String
options
else
diff --git a/actionpack/lib/action_controller/caching/sweeping.rb b/actionpack/lib/action_controller/caching/sweeping.rb
index 871f41bfdd..cf16417e84 100644
--- a/actionpack/lib/action_controller/caching/sweeping.rb
+++ b/actionpack/lib/action_controller/caching/sweeping.rb
@@ -30,9 +30,7 @@ module ActionController #:nodoc:
# cache_sweeper OpenBar::Sweeper, :only => [ :edit, :destroy, :share ]
# end
module Sweeping
- def self.included(base) #:nodoc:
- base.extend(ClassMethods)
- end
+ extend ActiveSupport::Concern
module ClassMethods #:nodoc:
def cache_sweeper(*sweepers)
diff --git a/actionpack/lib/action_controller/deprecated.rb b/actionpack/lib/action_controller/deprecated.rb
index a4eef07841..9f2de57033 100644
--- a/actionpack/lib/action_controller/deprecated.rb
+++ b/actionpack/lib/action_controller/deprecated.rb
@@ -1,5 +1,3 @@
ActionController::AbstractRequest = ActionController::Request = ActionDispatch::Request
ActionController::AbstractResponse = ActionController::Response = ActionDispatch::Response
ActionController::Routing = ActionDispatch::Routing
-ActionController::Routing::Routes = ActionDispatch::Routing::RouteSet.new
-ActionController::UrlWriter = ActionController::UrlFor
diff --git a/actionpack/lib/action_controller/deprecated/base.rb b/actionpack/lib/action_controller/deprecated/base.rb
new file mode 100644
index 0000000000..1d05b3fbd6
--- /dev/null
+++ b/actionpack/lib/action_controller/deprecated/base.rb
@@ -0,0 +1,131 @@
+module ActionController
+ class Base
+ class << self
+ def deprecated_config_accessor(option, message = nil)
+ deprecated_config_reader(option, message)
+ deprecated_config_writer(option, message)
+ end
+
+ def deprecated_config_reader(option, message = nil)
+ message ||= "Reading #{option} directly from ActionController::Base is deprecated. " \
+ "Please read it from config.#{option}"
+
+ self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
+ def #{option}
+ ActiveSupport::Deprecation.warn #{message.inspect}, caller
+ config.#{option}
+ end
+ RUBY
+ end
+
+ def deprecated_config_writer(option, message = nil)
+ message ||= "Setting #{option} directly on ActionController::Base is deprecated. " \
+ "Please set it on config.action_controller.#{option}"
+
+ self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
+ def #{option}=(val)
+ ActiveSupport::Deprecation.warn #{message.inspect}, caller
+ config.#{option} = val
+ end
+ RUBY
+ end
+
+ def consider_all_requests_local
+ ActiveSupport::Deprecation.warn "ActionController::Base.consider_all_requests_local is deprecated, " <<
+ "use Rails.application.config.consider_all_requests_local instead", caller
+ Rails.application.config.consider_all_requests_local
+ end
+
+ def consider_all_requests_local=(value)
+ ActiveSupport::Deprecation.warn "ActionController::Base.consider_all_requests_local= is deprecated. " <<
+ "Please configure it on your application with config.consider_all_requests_local=", caller
+ Rails.application.config.consider_all_requests_local = value
+ end
+
+ def allow_concurrency
+ ActiveSupport::Deprecation.warn "ActionController::Base.allow_concurrency is deprecated, " <<
+ "use Rails.application.config.allow_concurrency instead", caller
+ Rails.application.config.allow_concurrency
+ end
+
+ def allow_concurrency=(value)
+ ActiveSupport::Deprecation.warn "ActionController::Base.allow_concurrency= is deprecated. " <<
+ "Please configure it on your application with config.allow_concurrency=", caller
+ Rails.application.config.allow_concurrency = value
+ end
+
+ def ip_spoofing_check=(value)
+ ActiveSupport::Deprecation.warn "ActionController::Base.ip_spoofing_check= is deprecated. " <<
+ "Please configure it on your application with config.action_dispatch.ip_spoofing_check=", caller
+ Rails.application.config.action_dispatch.ip_spoofing_check = value
+ end
+
+ def ip_spoofing_check
+ ActiveSupport::Deprecation.warn "ActionController::Base.ip_spoofing_check is deprecated. " <<
+ "Configuring ip_spoofing_check on the application configures a middleware.", caller
+ Rails.application.config.action_disaptch.ip_spoofing_check
+ end
+
+ def trusted_proxies=(value)
+ ActiveSupport::Deprecation.warn "ActionController::Base.trusted_proxies= is deprecated. " <<
+ "Please configure it on your application with config.action_dispatch.trusted_proxies=", caller
+ Rails.application.config.action_dispatch.ip_spoofing_check = value
+ end
+
+ def trusted_proxies
+ ActiveSupport::Deprecation.warn "ActionController::Base.trusted_proxies is deprecated. " <<
+ "Configuring trusted_proxies on the application configures a middleware.", caller
+ Rails.application.config.action_dispatch.ip_spoofing_check = value
+ end
+
+ def session(*args)
+ ActiveSupport::Deprecation.warn(
+ "Disabling sessions for a single controller has been deprecated. " +
+ "Sessions are now lazy loaded. So if you don't access them, " +
+ "consider them off. You can still modify the session cookie " +
+ "options with request.session_options.", caller)
+ end
+
+ def session=(value)
+ ActiveSupport::Deprecation.warn "ActionController::Base.session= is deprecated. " <<
+ "Please configure it on your application with config.session_store :cookie_store, :key => '....'", caller
+ if value.delete(:disabled)
+ Rails.application.config.session_store :disabled
+ else
+ store = Rails.application.config.session_store
+ Rails.application.config.session_store store, value
+ end
+ end
+
+ # Controls the resource action separator
+ def resource_action_separator
+ @resource_action_separator ||= "/"
+ end
+
+ def resource_action_separator=(val)
+ ActiveSupport::Deprecation.warn "ActionController::Base.resource_action_separator is deprecated and only " \
+ "works with the deprecated router DSL."
+ @resource_action_separator = val
+ end
+
+ def use_accept_header
+ ActiveSupport::Deprecation.warn "ActionController::Base.use_accept_header doesn't do anything anymore. " \
+ "The accept header is always taken into account."
+ end
+
+ def use_accept_header=(val)
+ use_accept_header
+ end
+ end
+
+ deprecated_config_writer :session_store
+ deprecated_config_writer :session_options
+ deprecated_config_accessor :relative_url_root, "relative_url_root is ineffective. Please stop using it"
+ deprecated_config_accessor :assets_dir
+ deprecated_config_accessor :javascripts_dir
+ deprecated_config_accessor :stylesheets_dir
+
+ delegate :consider_all_requests_local, :consider_all_requests_local=,
+ :allow_concurrency, :allow_concurrency=, :to => :"self.class"
+ end
+end \ No newline at end of file
diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb
index 2b35e111ec..eebd2c943a 100644
--- a/actionpack/lib/action_controller/metal.rb
+++ b/actionpack/lib/action_controller/metal.rb
@@ -34,7 +34,8 @@ module ActionController
# and response object available. You might wish to control the
# environment and response manually for performance reasons.
- attr_internal :status, :headers, :content_type, :response
+ attr_internal :status, :headers, :content_type, :response, :request
+ delegate :session, :to => "@_request"
def initialize(*)
@_headers = {}
@@ -49,6 +50,14 @@ module ActionController
headers["Content-Type"] = type.to_s
end
+ def content_type
+ headers["Content-Type"]
+ end
+
+ def location
+ headers["Location"]
+ end
+
def location=(url)
headers["Location"] = url
end
@@ -58,8 +67,9 @@ module ActionController
end
# :api: private
- def dispatch(name, env)
- @_env = env
+ def dispatch(name, request)
+ @_request = request
+ @_env = request.env
@_env['action_controller.instance'] = self
process(name)
to_a
@@ -70,31 +80,12 @@ module ActionController
response ? response.to_a : [status, headers, response_body]
end
- class ActionEndpoint
- @@endpoints = Hash.new {|h,k| h[k] = Hash.new {|sh,sk| sh[sk] = {} } }
-
- def self.for(controller, action, stack)
- @@endpoints[controller][action][stack] ||= begin
- endpoint = new(controller, action)
- stack.build(endpoint)
- end
- end
-
- def initialize(controller, action)
- @controller, @action = controller, action
- @_formats = [Mime::HTML]
- end
-
- def call(env)
- @controller.new.dispatch(@action, env)
- end
- end
-
class_attribute :middleware_stack
self.middleware_stack = ActionDispatch::MiddlewareStack.new
def self.inherited(base)
self.middleware_stack = base.middleware_stack.dup
+ super
end
def self.use(*args)
@@ -118,8 +109,10 @@ module ActionController
#
# ==== Returns
# Proc:: A rack application
- def self.action(name)
- ActionEndpoint.for(self, name, middleware_stack)
+ def self.action(name, klass = ActionDispatch::Request)
+ middleware_stack.build do |env|
+ new.dispatch(name, klass.new(env))
+ end
end
end
end
diff --git a/actionpack/lib/action_controller/metal/compatibility.rb b/actionpack/lib/action_controller/metal/compatibility.rb
index a1cfa32d4d..ab8d87b2c4 100644
--- a/actionpack/lib/action_controller/metal/compatibility.rb
+++ b/actionpack/lib/action_controller/metal/compatibility.rb
@@ -2,26 +2,23 @@ module ActionController
module Compatibility
extend ActiveSupport::Concern
- include AbstractController::Compatibility
-
class ::ActionController::ActionControllerError < StandardError #:nodoc:
end
+ module ClassMethods
+ end
+
# Temporary hax
included do
::ActionController::UnknownAction = ::AbstractController::ActionNotFound
::ActionController::DoubleRenderError = ::AbstractController::DoubleRenderError
- cattr_accessor :session_options
- self.session_options = {}
-
- cattr_accessor :relative_url_root
- self.relative_url_root = ENV['RAILS_RELATIVE_URL_ROOT']
+ # ROUTES TODO: This should be handled by a middleware and route generation
+ # should be able to handle SCRIPT_NAME
+ self.config.relative_url_root = ENV['RAILS_RELATIVE_URL_ROOT']
class << self
delegate :default_charset=, :to => "ActionDispatch::Response"
- delegate :resources_path_names, :to => "ActionController::Routing::Routes"
- delegate :resources_path_names=, :to => "ActionController::Routing::Routes"
end
# cattr_reader :protected_instance_variables
@@ -32,31 +29,17 @@ module ActionController
@before_filter_chain_aborted @_headers @_params
@_response)
- # Controls the resource action separator
- cattr_accessor :resource_action_separator
- self.resource_action_separator = "/"
-
- cattr_accessor :use_accept_header
- self.use_accept_header = true
+ def rescue_action(env)
+ raise env["action_dispatch.rescue.exception"]
+ end
self.page_cache_directory = defined?(Rails.public_path) ? Rails.public_path : ""
-
- # 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
-
- cattr_accessor :ip_spoofing_check
- self.ip_spoofing_check = true
-
- cattr_accessor :trusted_proxies
end
# For old tests
def initialize_template_class(*) end
def assign_shortcuts(*) end
- # TODO: Remove this after we flip
def template
@template ||= view_context
end
@@ -66,52 +49,20 @@ module ActionController
super
end
- module ClassMethods
- def consider_all_requests_local
- ActiveSupport::Deprecation.warn "ActionController::Base.consider_all_requests_local is deprecated, " <<
- "use Rails.application.config.consider_all_requests_local instead"
- Rails.application.config.consider_all_requests_local
- end
-
- def consider_all_requests_local=(value)
- ActiveSupport::Deprecation.warn "ActionController::Base.consider_all_requests_local= is no longer effective. " <<
- "Please configure it on your application with config.consider_all_requests_local="
- Rails.application.config.consider_all_requests_local = value
- end
-
- def allow_concurrency
- ActiveSupport::Deprecation.warn "ActionController::Base.allow_concurrency is deprecated, " <<
- "use Rails.application.config.allow_concurrency instead"
- Rails.application.config.allow_concurrency
- end
-
- def allow_concurrency=(value)
- ActiveSupport::Deprecation.warn "ActionController::Base.allow_concurrency= is no longer effective. " <<
- "Please configure it on your application with config.allow_concurrency="
- Rails.application.config.allow_concurrency = value
- end
-
- def rescue_action(env)
- raise env["action_dispatch.rescue.exception"]
- end
-
- # Defines the storage option for cached fragments
- def cache_store=(store_option)
- @@cache_store = ActiveSupport::Cache.lookup_store(store_option)
- end
- end
-
- delegate :consider_all_requests_local, :consider_all_requests_local=,
- :allow_concurrency, :allow_concurrency=, :to => :"self.class"
-
- def render_to_body(options)
- if options.is_a?(Hash) && options.key?(:template)
- options[:template].sub!(/^\//, '')
+ def _normalize_options(options)
+ if options[:action] && options[:action].to_s.include?(?/)
+ ActiveSupport::Deprecation.warn "Giving a path to render :action is deprecated. " <<
+ "Please use render :template instead", caller
+ options[:template] = options.delete(:action)
end
options[:text] = nil if options.delete(:nothing) == true
options[:text] = " " if options.key?(:text) && options[:text].nil?
+ super
+ end
+ def render_to_body(options)
+ options[:template].sub!(/^\//, '') if options.key?(:template)
super || " "
end
@@ -126,18 +77,5 @@ module ActionController
def performed?
response_body
end
-
- # ==== Request only view path switching ====
- def append_view_path(path)
- view_paths.push(*path)
- end
-
- def prepend_view_path(path)
- view_paths.unshift(*path)
- end
-
- def view_paths
- view_context.view_paths
- end
end
end
diff --git a/actionpack/lib/action_controller/metal/configuration.rb b/actionpack/lib/action_controller/metal/configuration.rb
deleted file mode 100644
index 5c829853b7..0000000000
--- a/actionpack/lib/action_controller/metal/configuration.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-module ActionController
- module Configuration
- extend ActiveSupport::Concern
-
- def config
- @config ||= self.class.config
- end
-
- def config=(config)
- @config = config
- end
-
- module ClassMethods
- def default_config
- @default_config ||= {}
- end
-
- def config
- self.config ||= default_config
- end
-
- def config=(config)
- @config = ActiveSupport::OrderedHash.new
- @config.merge!(config)
- end
- end
- end
-end \ No newline at end of file
diff --git a/actionpack/lib/action_controller/metal/head.rb b/actionpack/lib/action_controller/metal/head.rb
index 37be8b3999..a5c9910d68 100644
--- a/actionpack/lib/action_controller/metal/head.rb
+++ b/actionpack/lib/action_controller/metal/head.rb
@@ -1,6 +1,7 @@
module ActionController
module Head
extend ActiveSupport::Concern
+
include ActionController::UrlFor
# Return a response that has no content (merely headers). The options
diff --git a/actionpack/lib/action_controller/metal/helpers.rb b/actionpack/lib/action_controller/metal/helpers.rb
index 1b5a4c3080..8efe01e37b 100644
--- a/actionpack/lib/action_controller/metal/helpers.rb
+++ b/actionpack/lib/action_controller/metal/helpers.rb
@@ -86,7 +86,7 @@ module ActionController
end
private
- # Overwrite _modules_for_helpers to accept :all as argument, which loads
+ # Overwrite modules_for_helpers to accept :all as argument, which loads
# all helpers in helpers_dir.
#
# ==== Parameters
@@ -95,7 +95,7 @@ module ActionController
# ==== Returns
# Array[Module]:: A normalized list of modules for the list of
# helpers provided.
- def _modules_for_helpers(args)
+ def modules_for_helpers(args)
args += all_application_helpers if args.delete(:all)
super(args)
end
diff --git a/actionpack/lib/action_controller/metal/hide_actions.rb b/actionpack/lib/action_controller/metal/hide_actions.rb
index e893acffdf..3358d80c35 100644
--- a/actionpack/lib/action_controller/metal/hide_actions.rb
+++ b/actionpack/lib/action_controller/metal/hide_actions.rb
@@ -15,10 +15,8 @@ module ActionController
# Overrides AbstractController::Base#action_method? to return false if the
# action name is in the list of hidden actions.
- def action_method?(action_name)
- self.class.visible_action?(action_name) do
- !self.class.hidden_actions.include?(action_name) && super
- end
+ def method_for_action(action_name)
+ self.class.visible_action?(action_name) && super
end
module ClassMethods
@@ -31,13 +29,13 @@ module ActionController
end
def inherited(klass)
- klass.instance_variable_set("@visible_actions", {})
+ klass.class_eval { @visible_actions = {} }
super
end
def visible_action?(action_name)
return @visible_actions[action_name] if @visible_actions.key?(action_name)
- @visible_actions[action_name] = yield
+ @visible_actions[action_name] = !hidden_actions.include?(action_name)
end
# Overrides AbstractController::Base#action_methods to remove any methods
diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb
index 0f35a7c040..6ec788f302 100644
--- a/actionpack/lib/action_controller/metal/http_authentication.rb
+++ b/actionpack/lib/action_controller/metal/http_authentication.rb
@@ -124,7 +124,7 @@ module ActionController
end
def authenticate(request, &login_procedure)
- unless authorization(request).blank?
+ unless request.authorization.blank?
login_procedure.call(*user_name_and_password(request))
end
end
@@ -133,15 +133,8 @@ module ActionController
decode_credentials(request).split(/:/, 2)
end
- def authorization(request)
- request.env['HTTP_AUTHORIZATION'] ||
- request.env['X-HTTP_AUTHORIZATION'] ||
- request.env['X_HTTP_AUTHORIZATION'] ||
- request.env['REDIRECT_X_HTTP_AUTHORIZATION']
- end
-
def decode_credentials(request)
- ActiveSupport::Base64.decode64(authorization(request).split(' ', 2).last || '')
+ ActiveSupport::Base64.decode64(request.authorization.split(' ', 2).last || '')
end
def encode_credentials(user_name, password)
@@ -165,7 +158,7 @@ module ActionController
# Authenticate with HTTP Digest, returns true or false
def authenticate_with_http_digest(realm = "Application", &password_procedure)
- HttpAuthentication::Digest.authenticate(request, realm, &password_procedure)
+ HttpAuthentication::Digest.authenticate(config.secret, request, realm, &password_procedure)
end
# Render output including the HTTP Digest authentication header
@@ -175,30 +168,23 @@ module ActionController
end
# Returns false on a valid response, true otherwise
- def authenticate(request, realm, &password_procedure)
- authorization(request) && validate_digest_response(request, realm, &password_procedure)
- end
-
- def authorization(request)
- request.env['HTTP_AUTHORIZATION'] ||
- request.env['X-HTTP_AUTHORIZATION'] ||
- request.env['X_HTTP_AUTHORIZATION'] ||
- request.env['REDIRECT_X_HTTP_AUTHORIZATION']
+ def authenticate(secret_key, request, realm, &password_procedure)
+ request.authorization && validate_digest_response(secret_key, request, realm, &password_procedure)
end
# Returns false unless the request credentials response value matches the expected value.
# First try the password as a ha1 digest password. If this fails, then try it as a plain
# text password.
- def validate_digest_response(request, realm, &password_procedure)
+ def validate_digest_response(secret_key, request, realm, &password_procedure)
credentials = decode_credentials_header(request)
- valid_nonce = validate_nonce(request, credentials[:nonce])
+ valid_nonce = validate_nonce(secret_key, request, credentials[:nonce])
- if valid_nonce && realm == credentials[:realm] && opaque == credentials[:opaque]
+ if valid_nonce && realm == credentials[:realm] && opaque(secret_key) == credentials[:opaque]
password = password_procedure.call(credentials[:username])
return false unless password
method = request.env['rack.methodoverride.original_method'] || request.env['REQUEST_METHOD']
- uri = credentials[:uri][0,1] == '/' ? request.request_uri : request.url
+ uri = credentials[:uri][0,1] == '/' ? request.fullpath : request.url
[true, false].any? do |password_is_ha1|
expected = expected_response(method, uri, credentials, password, password_is_ha1)
@@ -226,7 +212,7 @@ module ActionController
end
def decode_credentials_header(request)
- decode_credentials(authorization(request))
+ decode_credentials(request.authorization)
end
def decode_credentials(header)
@@ -238,6 +224,9 @@ module ActionController
end
def authentication_header(controller, realm)
+ secret_key = controller.config.secret
+ nonce = self.nonce(secret_key)
+ opaque = opaque(secret_key)
controller.headers["WWW-Authenticate"] = %(Digest realm="#{realm}", qop="auth", algorithm=MD5, nonce="#{nonce}", opaque="#{opaque}")
end
@@ -280,7 +269,7 @@ module ActionController
# The nonce is opaque to the client. Composed of Time, and hash of Time with secret
# key from the Rails session secret generated upon creation of project. Ensures
# the time cannot be modified by client.
- def nonce(time = Time.now)
+ def nonce(secret_key, time = Time.now)
t = time.to_i
hashed = [t, secret_key]
digest = ::Digest::MD5.hexdigest(hashed.join(":"))
@@ -292,21 +281,16 @@ module ActionController
# Can be much shorter if the Stale directive is implemented. This would
# allow a user to use new nonce without prompting user again for their
# username and password.
- def validate_nonce(request, value, seconds_to_timeout=5*60)
+ def validate_nonce(secret_key, request, value, seconds_to_timeout=5*60)
t = ActiveSupport::Base64.decode64(value).split(":").first.to_i
- nonce(t) == value && (t - Time.now.to_i).abs <= seconds_to_timeout
+ nonce(secret_key, t) == value && (t - Time.now.to_i).abs <= seconds_to_timeout
end
# Opaque based on random generation - but changing each request?
- def opaque()
+ def opaque(secret_key)
::Digest::MD5.hexdigest(secret_key)
end
- # Set in /initializers/session_store.rb, and loaded even if sessions are not in use.
- def secret_key
- ActionController::Base.session_options[:secret]
- end
-
end
end
end
diff --git a/actionpack/lib/action_controller/metal/implicit_render.rb b/actionpack/lib/action_controller/metal/implicit_render.rb
new file mode 100644
index 0000000000..282dcf66b3
--- /dev/null
+++ b/actionpack/lib/action_controller/metal/implicit_render.rb
@@ -0,0 +1,21 @@
+module ActionController
+ module ImplicitRender
+ def send_action(*)
+ ret = super
+ default_render unless response_body
+ ret
+ end
+
+ def default_render
+ render
+ end
+
+ def method_for_action(action_name)
+ super || begin
+ if template_exists?(action_name.to_s, _prefix)
+ "default_render"
+ end
+ end
+ end
+ end
+end \ No newline at end of file
diff --git a/actionpack/lib/action_controller/metal/instrumentation.rb b/actionpack/lib/action_controller/metal/instrumentation.rb
index 85035dc09c..d69de65f28 100644
--- a/actionpack/lib/action_controller/metal/instrumentation.rb
+++ b/actionpack/lib/action_controller/metal/instrumentation.rb
@@ -20,7 +20,7 @@ module ActionController
:params => request.filtered_parameters,
:formats => request.formats.map(&:to_sym),
:method => request.method,
- :path => (request.request_uri rescue "unknown")
+ :path => (request.fullpath rescue "unknown")
}
ActiveSupport::Notifications.instrument("action_controller.start_processing", raw_payload.dup)
diff --git a/actionpack/lib/action_controller/metal/rack_delegation.rb b/actionpack/lib/action_controller/metal/rack_delegation.rb
index bb55383631..37106733cb 100644
--- a/actionpack/lib/action_controller/metal/rack_delegation.rb
+++ b/actionpack/lib/action_controller/metal/rack_delegation.rb
@@ -6,14 +6,11 @@ module ActionController
extend ActiveSupport::Concern
included do
- delegate :session, :to => "@_request"
delegate :headers, :status=, :location=, :content_type=,
:status, :location, :content_type, :to => "@_response"
- attr_internal :request
end
- def dispatch(action, env)
- @_request = ActionDispatch::Request.new(env)
+ def dispatch(action, request)
@_response = ActionDispatch::Response.new
@_response.request = request
super
diff --git a/actionpack/lib/action_controller/metal/redirecting.rb b/actionpack/lib/action_controller/metal/redirecting.rb
index faf0589fd2..25e4e18493 100644
--- a/actionpack/lib/action_controller/metal/redirecting.rb
+++ b/actionpack/lib/action_controller/metal/redirecting.rb
@@ -11,6 +11,7 @@ module ActionController
extend ActiveSupport::Concern
include AbstractController::Logger
+ include ActionController::RackDelegation
include ActionController::UrlFor
# Redirects the browser to the target specified in +options+. This parameter can take one of three forms:
diff --git a/actionpack/lib/action_controller/metal/renderers.rb b/actionpack/lib/action_controller/metal/renderers.rb
index 639b508746..49d3d6b466 100644
--- a/actionpack/lib/action_controller/metal/renderers.rb
+++ b/actionpack/lib/action_controller/metal/renderers.rb
@@ -19,7 +19,7 @@ module ActionController
<<-RUBY_EVAL
if options.key?(:#{name})
_process_options(options)
- return _render_option_#{name}(options[:#{name}], options)
+ return _render_option_#{name}(options.delete(:#{name}), options)
end
RUBY_EVAL
end
diff --git a/actionpack/lib/action_controller/metal/rendering.rb b/actionpack/lib/action_controller/metal/rendering.rb
index 0aae9f8579..f892bd9b91 100644
--- a/actionpack/lib/action_controller/metal/rendering.rb
+++ b/actionpack/lib/action_controller/metal/rendering.rb
@@ -2,68 +2,54 @@ module ActionController
module Rendering
extend ActiveSupport::Concern
- included do
- include AbstractController::Rendering
- include AbstractController::LocalizedCache
- end
+ include ActionController::RackDelegation
+ include AbstractController::Rendering
- def process_action(*)
- self.formats = request.formats.map {|x| x.to_sym}
+ def process(*)
+ self.formats = request.formats.map { |x| x.to_sym }
super
end
def render(*args)
- if response_body
- raise ::AbstractController::DoubleRenderError
- end
-
- args << {} unless args.last.is_a?(Hash)
- super(*args)
- self.content_type ||= args.last[:_template].mime_type.to_s
- response_body
- end
-
- def render_to_body(options)
- _process_options(options)
+ raise ::AbstractController::DoubleRenderError if response_body
super
+ response_body
end
private
- def _render_partial(options)
- options[:partial] = action_name if options[:partial] == true
- options[:_details] = {:formats => formats}
- super
+ def _normalize_args(action=nil, options={}, &blk)
+ options = super
+ options[:update] = blk if block_given?
+ options
end
- def format_for_text
- formats.first
+ def _normalize_options(options)
+ if options.key?(:text) && options[:text].respond_to?(:to_text)
+ options[:text] = options[:text].to_text
+ end
+
+ if options[:status]
+ options[:status] = Rack::Utils.status_code(options[:status])
+ end
+
+ super
end
def _process_options(options)
status, content_type, location = options.values_at(:status, :content_type, :location)
+
self.status = status if status
self.content_type = content_type if content_type
self.headers["Location"] = url_for(location) if location
- end
- def _normalize_options(action=nil, options={}, &blk)
- case action
- when NilClass
- when Hash
- options = super(action.delete(:action), action)
- when String, Symbol
- options = super
- else
- options.merge! :partial => action
- end
-
- if options[:status]
- options[:status] = Rack::Utils.status_code(options[:status])
- end
+ super
+ end
- options[:update] = blk if block_given?
- options
+ def _with_template_hook(template)
+ super
+ self.content_type ||= template.mime_type.to_s
end
+
end
end
diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
index 276c703307..39a809657b 100644
--- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb
+++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
@@ -12,11 +12,10 @@ module ActionController #:nodoc:
included do
# 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
+ config.request_forgery_protection_token ||= :authenticity_token
# Controls whether request forgergy protection is turned on or not. Turned off by default only in test mode.
- class_attribute :allow_forgery_protection
- self.allow_forgery_protection = true
+ config.allow_forgery_protection ||= true
helper_method :form_authenticity_token
helper_method :protect_against_forgery?
@@ -80,9 +79,47 @@ module ActionController #:nodoc:
self.request_forgery_protection_token ||= :authenticity_token
before_filter :verify_authenticity_token, options
end
+
+ def request_forgery_protection_token
+ config.request_forgery_protection_token
+ end
+
+ def request_forgery_protection_token=(val)
+ config.request_forgery_protection_token = val
+ end
+
+ def allow_forgery_protection
+ config.allow_forgery_protection
+ end
+
+ def allow_forgery_protection=(val)
+ config.allow_forgery_protection = val
+ end
end
protected
+
+ def protect_from_forgery(options = {})
+ self.request_forgery_protection_token ||= :authenticity_token
+ before_filter :verify_authenticity_token, options
+ end
+
+ def request_forgery_protection_token
+ config.request_forgery_protection_token
+ end
+
+ def request_forgery_protection_token=(val)
+ config.request_forgery_protection_token = val
+ end
+
+ def allow_forgery_protection
+ config.allow_forgery_protection
+ end
+
+ def allow_forgery_protection=(val)
+ config.allow_forgery_protection = val
+ end
+
# The actual before_filter that is used. Modify this to change how you handle unverified requests.
def verify_authenticity_token
verified_request? || raise(ActionController::InvalidAuthenticityToken)
@@ -109,7 +146,7 @@ module ActionController #:nodoc:
end
def protect_against_forgery?
- self.class.allow_forgery_protection
+ config.allow_forgery_protection
end
end
end
diff --git a/actionpack/lib/action_controller/metal/session_management.rb b/actionpack/lib/action_controller/metal/session_management.rb
index d70f40ce7a..91d89ff9a4 100644
--- a/actionpack/lib/action_controller/metal/session_management.rb
+++ b/actionpack/lib/action_controller/metal/session_management.rb
@@ -2,44 +2,8 @@ module ActionController #:nodoc:
module SessionManagement #:nodoc:
extend ActiveSupport::Concern
- include ActionController::Configuration
-
module ClassMethods
- # Set the session store to be used for keeping the session data between requests.
- # By default, sessions are stored in browser cookies (<tt>:cookie_store</tt>),
- # but you can also specify one of the other included stores (<tt>:active_record_store</tt>,
- # <tt>:mem_cache_store</tt>, or your own custom class.
- def session_store=(store)
- if store == :active_record_store
- self.session_store = ActiveRecord::SessionStore
- else
- @@session_store = store.is_a?(Symbol) ?
- ActionDispatch::Session.const_get(store.to_s.camelize) :
- store
- end
- end
-
- # Returns the session store class currently used.
- def session_store
- if defined? @@session_store
- @@session_store
- else
- ActionDispatch::Session::CookieStore
- end
- end
-
- def session=(options = {})
- self.session_store = nil if options.delete(:disabled)
- session_options.merge!(options)
- end
- def session(*args)
- ActiveSupport::Deprecation.warn(
- "Disabling sessions for a single controller has been deprecated. " +
- "Sessions are now lazy loaded. So if you don't access them, " +
- "consider them off. You can still modify the session cookie " +
- "options with request.session_options.", caller)
- end
end
end
end
diff --git a/actionpack/lib/action_controller/metal/streaming.rb b/actionpack/lib/action_controller/metal/streaming.rb
index 8f03b8bb17..753af3dc58 100644
--- a/actionpack/lib/action_controller/metal/streaming.rb
+++ b/actionpack/lib/action_controller/metal/streaming.rb
@@ -9,18 +9,13 @@ module ActionController #:nodoc:
DEFAULT_SEND_FILE_OPTIONS = {
:type => 'application/octet-stream'.freeze,
:disposition => 'attachment'.freeze,
- :stream => true,
- :buffer_size => 4096,
- :x_sendfile => false
}.freeze
- X_SENDFILE_HEADER = 'X-Sendfile'.freeze
-
protected
- # Sends the file, by default streaming it 4096 bytes at a time. This way the
- # whole file doesn't need to be read into memory at once. This makes it
- # feasible to send even large files. You can optionally turn off streaming
- # and send the whole file at once.
+ # Sends the file. This uses a server-appropriate method (such as X-Sendfile)
+ # via the Rack::Sendfile middleware. The header to use is set via
+ # config.action_dispatch.x_sendfile_header, and defaults to "X-Sendfile".
+ # Your server can also configure this for you by setting the X-Sendfile-Type header.
#
# Be careful to sanitize the path parameter if it is coming from a web
# page. <tt>send_file(params[:path])</tt> allows a malicious user to
@@ -31,24 +26,12 @@ module ActionController #:nodoc:
# Defaults to <tt>File.basename(path)</tt>.
# * <tt>:type</tt> - specifies an HTTP content type. Defaults to 'application/octet-stream'. You can specify
# either a string or a symbol for a registered type register with <tt>Mime::Type.register</tt>, for example :json
- # * <tt>:length</tt> - used to manually override the length (in bytes) of the content that
- # is going to be sent to the client. Defaults to <tt>File.size(path)</tt>.
# * <tt>:disposition</tt> - specifies whether the file will be shown inline or downloaded.
# Valid values are 'inline' and 'attachment' (default).
- # * <tt>:stream</tt> - whether to send the file to the user agent as it is read (+true+)
- # or to read the entire file before sending (+false+). Defaults to +true+.
- # * <tt>:buffer_size</tt> - specifies size (in bytes) of the buffer used to stream the file.
- # Defaults to 4096.
# * <tt>:status</tt> - specifies the status code to send with the response. Defaults to '200 OK'.
# * <tt>:url_based_filename</tt> - set to +true+ if you want the browser guess the filename from
# the URL, which is necessary for i18n filenames on certain browsers
# (setting <tt>:filename</tt> overrides this option).
- # * <tt>:x_sendfile</tt> - uses X-Sendfile to send the file when set to +true+. This is currently
- # only available with Lighttpd/Apache2 and specific modules installed and activated. Since this
- # uses the web server to send the file, this may lower memory consumption on your server and
- # it will not block your application for further requests.
- # See http://blog.lighttpd.net/articles/2006/07/02/x-sendfile and
- # http://tn123.ath.cx/mod_xsendfile/ for details. Defaults to +false+.
#
# The default Content-Type and Content-Disposition headers are
# set to download arbitrary binary files in as many browsers as
@@ -81,29 +64,16 @@ module ActionController #:nodoc:
def send_file(path, options = {}) #:doc:
raise MissingFile, "Cannot read file #{path}" unless File.file?(path) and File.readable?(path)
- options[:length] ||= File.size(path)
options[:filename] ||= File.basename(path) unless options[:url_based_filename]
send_file_headers! options
- @performed_render = false
-
if options[:x_sendfile]
- 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|
- len = options[:buffer_size] || 4096
- File.open(path, 'rb') do |file|
- while buf = file.read(len)
- output.write(buf)
- end
- end
- }
- else
- File.open(path, 'rb') { |file| render :status => options[:status], :text => file.read }
- end
+ ActiveSupport::Deprecation.warn(":x_sendfile is no longer needed in send_file", caller)
end
+
+ self.status = options[:status] || 200
+ self.content_type = options[:content_type] if options.key?(:content_type)
+ self.response_body = File.open(path, "rb")
end
# Sends the given binary data to the browser. This method is similar to
@@ -138,32 +108,35 @@ module ActionController #:nodoc:
# data to the browser, then use <tt>render :text => proc { ... }</tt>
# instead. See ActionController::Base#render for more information.
def send_data(data, options = {}) #:doc:
- send_file_headers! options.merge(:length => data.bytesize)
- render :status => options[:status], :text => data
+ send_file_headers! options.dup
+ render options.slice(:status, :content_type).merge(:text => data)
end
private
def send_file_headers!(options)
options.update(DEFAULT_SEND_FILE_OPTIONS.merge(options))
- [:length, :type, :disposition].each do |arg|
+ [:type, :disposition].each do |arg|
raise ArgumentError, ":#{arg} option required" if options[arg].nil?
end
- disposition = options[:disposition].dup || 'attachment'
+ if options.key?(:length)
+ ActiveSupport::Deprecation.warn("You do not need to provide the file's length", caller)
+ end
- disposition <<= %(; filename="#{options[:filename]}") if options[:filename]
+ disposition = options[:disposition]
+ disposition += %(; filename="#{options[:filename]}") if options[:filename]
content_type = options[:type]
if content_type.is_a?(Symbol)
- raise ArgumentError, "Unknown MIME type #{options[:type]}" unless Mime::EXTENSION_LOOKUP.key?(content_type.to_s)
- self.content_type = Mime::Type.lookup_by_extension(content_type.to_s)
+ extension = Mime[content_type]
+ raise ArgumentError, "Unknown MIME type #{options[:type]}" unless extension
+ self.content_type = extension
else
self.content_type = content_type
end
headers.merge!(
- 'Content-Length' => options[:length].to_s,
'Content-Disposition' => disposition,
'Content-Transfer-Encoding' => 'binary'
)
diff --git a/actionpack/lib/action_controller/metal/testing.rb b/actionpack/lib/action_controller/metal/testing.rb
index 707ad968f4..4b8c452d50 100644
--- a/actionpack/lib/action_controller/metal/testing.rb
+++ b/actionpack/lib/action_controller/metal/testing.rb
@@ -13,7 +13,6 @@ module ActionController
if cookies = @_request.env['action_dispatch.cookies']
cookies.write(@_response)
end
- @_response.body ||= self.response_body
@_response.prepare!
set_test_assigns
ret
diff --git a/actionpack/lib/action_controller/metal/url_for.rb b/actionpack/lib/action_controller/metal/url_for.rb
index 4f3ad07be5..10c7ca9021 100644
--- a/actionpack/lib/action_controller/metal/url_for.rb
+++ b/actionpack/lib/action_controller/metal/url_for.rb
@@ -1,165 +1,20 @@
-require 'active_support/core_ext/class/attribute'
-require 'active_support/core_ext/module/attribute_accessors'
-
module ActionController
- # In <b>routes.rb</b> one defines URL-to-controller mappings, but the reverse
- # is also possible: an URL can be generated from one of your routing definitions.
- # URL generation functionality is centralized in this module.
- #
- # See ActionController::Routing and ActionController::Resources for general
- # information about routing and routes.rb.
- #
- # <b>Tip:</b> If you need to generate URLs from your models or some other place,
- # then ActionController::UrlFor is what you're looking for. Read on for
- # an introduction.
- #
- # == URL generation from parameters
- #
- # As you may know, some functions - such as ActionController::Base#url_for
- # and ActionView::Helpers::UrlHelper#link_to, can generate URLs given a set
- # of parameters. For example, you've probably had the chance to write code
- # like this in one of your views:
- #
- # <%= link_to('Click here', :controller => 'users',
- # :action => 'new', :message => 'Welcome!') %>
- #
- # #=> Generates a link to: /users/new?message=Welcome%21
- #
- # link_to, and all other functions that require URL generation functionality,
- # actually use ActionController::UrlFor under the hood. And in particular,
- # they use the ActionController::UrlFor#url_for method. One can generate
- # the same path as the above example by using the following code:
- #
- # include UrlFor
- # url_for(:controller => 'users',
- # :action => 'new',
- # :message => 'Welcome!',
- # :only_path => true)
- # # => "/users/new?message=Welcome%21"
- #
- # Notice the <tt>:only_path => true</tt> part. This is because UrlFor has no
- # information about the website hostname that your Rails app is serving. So if you
- # want to include the hostname as well, then you must also pass the <tt>:host</tt>
- # argument:
- #
- # include UrlFor
- # url_for(:controller => 'users',
- # :action => 'new',
- # :message => 'Welcome!',
- # :host => 'www.example.com') # Changed this.
- # # => "http://www.example.com/users/new?message=Welcome%21"
- #
- # By default, all controllers and views have access to a special version of url_for,
- # that already knows what the current hostname is. So if you use url_for in your
- # controllers or your views, then you don't need to explicitly pass the <tt>:host</tt>
- # argument.
- #
- # For convenience reasons, mailers provide a shortcut for ActionController::UrlFor#url_for.
- # So within mailers, you only have to type 'url_for' instead of 'ActionController::UrlFor#url_for'
- # in full. However, mailers don't have hostname information, and what's why you'll still
- # have to specify the <tt>:host</tt> argument when generating URLs in mailers.
- #
- #
- # == URL generation for named routes
- #
- # UrlFor also allows one to access methods that have been auto-generated from
- # named routes. For example, suppose that you have a 'users' resource in your
- # <b>routes.rb</b>:
- #
- # map.resources :users
- #
- # This generates, among other things, the method <tt>users_path</tt>. By default,
- # this method is accessible from your controllers, views and mailers. If you need
- # to access this auto-generated method from other places (such as a model), then
- # you can do that by including ActionController::UrlFor in your class:
- #
- # class User < ActiveRecord::Base
- # include ActionController::UrlFor
- #
- # def base_uri
- # user_path(self)
- # end
- # end
- #
- # User.find(1).base_uri # => "/users/1"
- #
module UrlFor
extend ActiveSupport::Concern
- included do
- ActionController::Routing::Routes.install_helpers(self)
-
- # Including in a class uses an inheritable hash. Modules get a plain hash.
- if respond_to?(:class_attribute)
- class_attribute :default_url_options
- else
- mattr_accessor :default_url_options
- end
+ include ActionDispatch::Routing::UrlFor
- self.default_url_options = {}
+ def url_options
+ super.reverse_merge(
+ :host => request.host_with_port,
+ :protocol => request.protocol,
+ :_path_segments => request.symbolized_path_parameters
+ ).merge(:script_name => request.script_name)
end
- # Overwrite to implement a number of default options that all url_for-based methods will use. The default options should come in
- # the form of a hash, just like the one you would use for url_for directly. Example:
- #
- # def default_url_options(options)
- # { :project => @project.active? ? @project.url_name : "unknown" }
- # end
- #
- # As you can infer from the example, this is mostly useful for situations where you want to centralize dynamic decisions about the
- # urls as they stem from the business domain. Please note that any individual url_for call can always override the defaults set
- # by this method.
- def default_url_options(options = nil)
- self.class.default_url_options
- end
-
- def rewrite_options(options) #:nodoc:
- if options.delete(:use_defaults) != false && (defaults = default_url_options(options))
- defaults.merge(options)
- else
- options
- end
- end
-
- # Generate a url based on the options provided, default_url_options and the
- # routes defined in routes.rb. The following options are supported:
- #
- # * <tt>:only_path</tt> - If true, the relative url is returned. Defaults to +false+.
- # * <tt>:protocol</tt> - The protocol to connect to. Defaults to 'http'.
- # * <tt>:host</tt> - Specifies the host the link should be targeted at.
- # If <tt>:only_path</tt> is false, this option must be
- # provided either explicitly, or via +default_url_options+.
- # * <tt>:port</tt> - Optionally specify the port to connect to.
- # * <tt>:anchor</tt> - An anchor name to be appended to the path.
- # * <tt>:skip_relative_url_root</tt> - If true, the url is not constructed using the
- # +relative_url_root+ set in ActionController::Base.relative_url_root.
- # * <tt>:trailing_slash</tt> - If true, adds a trailing slash, as in "/archive/2009/"
- #
- # Any other key (<tt>:controller</tt>, <tt>:action</tt>, etc.) given to
- # +url_for+ is forwarded to the Routes module.
- #
- # Examples:
- #
- # url_for :controller => 'tasks', :action => 'testing', :host=>'somehost.org', :port=>'8080' # => 'http://somehost.org:8080/tasks/testing'
- # url_for :controller => 'tasks', :action => 'testing', :host=>'somehost.org', :anchor => 'ok', :only_path => true # => '/tasks/testing#ok'
- # url_for :controller => 'tasks', :action => 'testing', :trailing_slash=>true # => 'http://somehost.org/tasks/testing/'
- # url_for :controller => 'tasks', :action => 'testing', :host=>'somehost.org', :number => '33' # => 'http://somehost.org/tasks/testing?number=33'
- def url_for(options = {})
- options ||= {}
- case options
- when String
- options
- when Hash
- _url_rewriter.rewrite(rewrite_options(options))
- else
- polymorphic_url(options)
- end
- end
-
- protected
-
- def _url_rewriter
- ActionController::UrlRewriter
+ def _router
+ raise "In order to use #url_for, you must include the helpers of a particular " \
+ "router. For instance, `include Rails.application.routes.url_helpers"
end
end
-end
+end \ No newline at end of file
diff --git a/actionpack/lib/action_controller/middleware.rb b/actionpack/lib/action_controller/middleware.rb
index 17275793b7..2115b07b3e 100644
--- a/actionpack/lib/action_controller/middleware.rb
+++ b/actionpack/lib/action_controller/middleware.rb
@@ -6,7 +6,8 @@ module ActionController
end
def call(env)
- @controller.build(@app).dispatch(:index, env)
+ request = ActionDispatch::Request.new(env)
+ @controller.build(@app).dispatch(:index, request)
end
end
diff --git a/actionpack/lib/action_controller/polymorphic_routes.rb b/actionpack/lib/action_controller/polymorphic_routes.rb
index eaed00cfb7..ae363e300c 100644
--- a/actionpack/lib/action_controller/polymorphic_routes.rb
+++ b/actionpack/lib/action_controller/polymorphic_routes.rb
@@ -92,8 +92,7 @@ module ActionController
inflection = if options[:action].to_s == "new"
args.pop
:singular
- elsif (record.respond_to?(:new_record?) && record.new_record?) ||
- (record.respond_to?(:destroyed?) && record.destroyed?)
+ elsif (record.respond_to?(:persisted?) && !record.persisted?)
args.pop
:plural
elsif record.is_a?(Class)
diff --git a/actionpack/lib/action_controller/railtie.rb b/actionpack/lib/action_controller/railtie.rb
index 55a5c22ac0..6a3afbb157 100644
--- a/actionpack/lib/action_controller/railtie.rb
+++ b/actionpack/lib/action_controller/railtie.rb
@@ -1,30 +1,80 @@
-require "action_controller"
require "rails"
+require "action_controller"
require "action_view/railtie"
+require "active_support/core_ext/class/subclasses"
+require "active_support/deprecation/proxy_wrappers"
+require "active_support/deprecation"
module ActionController
class Railtie < Rails::Railtie
railtie_name :action_controller
- require "action_controller/railties/subscriber"
- subscriber ActionController::Railties::Subscriber.new
+ require "action_controller/railties/log_subscriber"
+ require "action_controller/railties/url_helpers"
+
+ ad = config.action_dispatch
+ config.action_controller.singleton_class.send(:define_method, :session) do
+ ActiveSupport::Deprecation.warn "config.action_controller.session has been " \
+ "renamed to config.action_dispatch.session.", caller
+ ad.session
+ end
+
+ config.action_controller.singleton_class.send(:define_method, :session=) do |val|
+ ActiveSupport::Deprecation.warn "config.action_controller.session has been " \
+ "renamed to config.action_dispatch.session.", caller
+ ad.session = val
+ end
+
+ config.action_controller.singleton_class.send(:define_method, :session_store) do
+ ActiveSupport::Deprecation.warn "config.action_controller.session_store has been " \
+ "renamed to config.action_dispatch.session_store.", caller
+ ad.session_store
+ end
+
+ config.action_controller.singleton_class.send(:define_method, :session_store=) do |val|
+ ActiveSupport::Deprecation.warn "config.action_controller.session_store has been " \
+ "renamed to config.action_dispatch.session_store.", caller
+ ad.session_store = val
+ end
+
+ log_subscriber ActionController::Railties::LogSubscriber.new
initializer "action_controller.logger" do
- ActionController::Base.logger ||= Rails.logger
+ ActionController.base_hook { self.logger ||= Rails.logger }
end
initializer "action_controller.set_configs" do |app|
- app.config.action_controller.each do |k,v|
- ActionController::Base.send "#{k}=", v
- end
+ paths = app.config.paths
+ ac = app.config.action_controller
+
+ ac.assets_dir = paths.public.to_a.first
+ ac.javascripts_dir = paths.public.javascripts.to_a.first
+ ac.stylesheets_dir = paths.public.stylesheets.to_a.first
+ ac.secret = app.config.cookie_secret
+
+ ActionController.base_hook { self.config.replace(ac) }
end
initializer "action_controller.initialize_framework_caches" do
- ActionController::Base.cache_store ||= RAILS_CACHE
+ ActionController.base_hook { self.cache_store ||= RAILS_CACHE }
end
initializer "action_controller.set_helpers_path" do |app|
- ActionController::Base.helpers_path = app.config.paths.app.helpers.to_a
+ ActionController.base_hook do
+ self.helpers_path = app.config.paths.app.helpers.to_a
+ end
+ end
+
+ initializer "action_controller.url_helpers" do |app|
+ ActionController.base_hook do
+ extend ::ActionController::Railtie::UrlHelpers.with(app.routes)
+ end
+
+ message = "ActionController::Routing::Routes is deprecated. " \
+ "Instead, use Rails.application.routes"
+
+ proxy = ActiveSupport::Deprecation::DeprecatedObjectProxy.new(app.routes, message)
+ ActionController::Routing::Routes = proxy
end
end
-end
+end \ No newline at end of file
diff --git a/actionpack/lib/action_controller/railties/subscriber.rb b/actionpack/lib/action_controller/railties/log_subscriber.rb
index 4499e82292..c2299d0b05 100644
--- a/actionpack/lib/action_controller/railties/subscriber.rb
+++ b/actionpack/lib/action_controller/railties/log_subscriber.rb
@@ -1,6 +1,6 @@
module ActionController
module Railties
- class Subscriber < Rails::Subscriber
+ class LogSubscriber < Rails::LogSubscriber
INTERNAL_PARAMS = %w(controller action format _method only_path)
def start_processing(event)
@@ -22,15 +22,7 @@ module ActionController
end
def send_file(event)
- message = if event.payload[:x_sendfile]
- header = ActionController::Streaming::X_SENDFILE_HEADER
- "Sent #{header} header %s"
- elsif event.payload[:stream]
- "Streamed file %s"
- else
- "Sent file %s"
- end
-
+ message = "Sent file %s"
message << " (%.1fms)"
info(message % [event.payload[:path], event.duration])
end
diff --git a/actionpack/lib/action_controller/railties/url_helpers.rb b/actionpack/lib/action_controller/railties/url_helpers.rb
new file mode 100644
index 0000000000..ad2a8d4ef3
--- /dev/null
+++ b/actionpack/lib/action_controller/railties/url_helpers.rb
@@ -0,0 +1,14 @@
+module ActionController
+ class Railtie
+ module UrlHelpers
+ def self.with(router)
+ Module.new do
+ define_method(:inherited) do |klass|
+ super(klass)
+ klass.send(:include, router.url_helpers)
+ end
+ end
+ end
+ end
+ end
+end \ No newline at end of file
diff --git a/actionpack/lib/action_controller/record_identifier.rb b/actionpack/lib/action_controller/record_identifier.rb
index 1165c3b7c5..3f966b1b64 100644
--- a/actionpack/lib/action_controller/record_identifier.rb
+++ b/actionpack/lib/action_controller/record_identifier.rb
@@ -60,13 +60,32 @@ module ActionController
#
# dom_id(Post.find(45), :edit) # => "edit_post_45"
def dom_id(record, prefix = nil)
- if record_id = record.id
+ if record_id = record_key_for_dom_id(record)
"#{dom_class(record, prefix)}#{JOIN}#{record_id}"
else
dom_class(record, prefix || NEW)
end
end
+ # Returns a string representation of the key attribute(s) that is suitable for use in an HTML DOM id.
+ # This can be overwritten to customize the default generated string representation if desired.
+ # If you need to read back a key from a dom_id in order to query for the underlying database record,
+ # you should write a helper like 'person_record_from_dom_id' that will extract the key either based
+ # on the default implementation (which just joins all key attributes with '-') or on your own
+ # overwritten version of the method. By default, this implementation passes the key string through a
+ # method that replaces all characters that are invalid inside DOM ids, with valid ones. You need to
+ # make sure yourself that your dom ids are valid, in case you overwrite this method.
+ def record_key_for_dom_id(record)
+ return record.id unless record.respond_to?(:to_model)
+ key = record.to_model.to_key
+ key ? sanitize_dom_id(key.join('_')) : key
+ end
+
+ # Replaces characters that are invalid in HTML DOM ids with valid ones.
+ def sanitize_dom_id(candidate_id)
+ candidate_id # TODO implement conversion to valid DOM id values
+ end
+
# Returns the plural class name of a record or class. Examples:
#
# plural_class_name(post) # => "posts"
diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb
index 14557ca782..cdb5db32aa 100644
--- a/actionpack/lib/action_controller/test_case.rb
+++ b/actionpack/lib/action_controller/test_case.rb
@@ -17,9 +17,9 @@ module ActionController
end
end
- def assign_parameters(controller_path, action, parameters = {})
+ def assign_parameters(router, controller_path, action, parameters = {})
parameters = parameters.symbolize_keys.merge(:controller => controller_path, :action => action)
- extra_keys = ActionController::Routing::Routes.extra_keys(parameters)
+ extra_keys = router.extra_keys(parameters)
non_path_parameters = get? ? query_parameters : request_parameters
parameters.each do |key, value|
if value.is_a? Fixnum
@@ -220,7 +220,7 @@ module ActionController
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|
+ %w(@router @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
@@ -236,7 +236,7 @@ module ActionController
@request.env['REQUEST_METHOD'] = http_method
parameters ||= {}
- @request.assign_parameters(@controller.class.name.underscore.sub(/_controller$/, ''), action.to_s, parameters)
+ @request.assign_parameters(@router, @controller.class.name.underscore.sub(/_controller$/, ''), action.to_s, parameters)
@request.session = ActionController::TestSession.new(session) unless session.nil?
@request.session["flash"] = @request.flash.update(flash || {})
@@ -322,6 +322,8 @@ module ActionController
@controller ||= klass.new rescue nil
end
+ @request.env.delete('PATH_INFO')
+
if @controller
@controller.request = @request
@controller.params = {}
@@ -335,13 +337,20 @@ module ActionController
private
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)
+ unless @request.env["PATH_INFO"]
+ options = @controller.__send__(:url_options).merge(parameters)
+ options.update(
+ :only_path => true,
+ :action => action,
+ :relative_url_root => nil,
+ :_path_segments => @request.symbolized_path_parameters)
+
+ url, query_string = @router.url_for(options).split("?", 2)
+
+ @request.env["SCRIPT_NAME"] = @controller.config.relative_url_root
+ @request.env["PATH_INFO"] = url
+ @request.env["QUERY_STRING"] = query_string || ""
end
end
- end
+ end
end
diff --git a/actionpack/lib/action_controller/url_rewriter.rb b/actionpack/lib/action_controller/url_rewriter.rb
deleted file mode 100644
index 933a1fa8f9..0000000000
--- a/actionpack/lib/action_controller/url_rewriter.rb
+++ /dev/null
@@ -1,76 +0,0 @@
-require 'active_support/core_ext/hash/except'
-
-module ActionController
- # Rewrites URLs for Base.redirect_to and Base.url_for in the controller.
- class UrlRewriter #:nodoc:
- RESERVED_OPTIONS = [:anchor, :params, :only_path, :host, :protocol, :port, :trailing_slash, :skip_relative_url_root]
-
- def initialize(request, parameters)
- @request, @parameters = request, parameters
- end
-
- def rewrite(options = {})
- options[:host] ||= @request.host_with_port
- options[:protocol] ||= @request.protocol
-
- self.class.rewrite(options, @request.symbolized_path_parameters) do |options|
- process_path_options(options)
- end
- end
-
- def to_str
- "#{@request.protocol}, #{@request.host_with_port}, #{@request.path}, #{@parameters[:controller]}, #{@parameters[:action]}, #{@request.parameters.inspect}"
- end
-
- alias_method :to_s, :to_str
-
- def self.rewrite(options, path_segments=nil)
- rewritten_url = ""
-
- unless options[:only_path]
- rewritten_url << (options[:protocol] || "http")
- rewritten_url << "://" unless rewritten_url.match("://")
- rewritten_url << rewrite_authentication(options)
-
- raise "Missing host to link to! Please provide :host parameter or set default_url_options[:host]" unless options[:host]
-
- rewritten_url << options[:host]
- rewritten_url << ":#{options.delete(:port)}" if options.key?(:port)
- end
-
- path_options = options.except(*RESERVED_OPTIONS)
- path_options = yield(path_options) if block_given?
- path = Routing::Routes.generate(path_options, path_segments || {})
-
- rewritten_url << ActionController::Base.relative_url_root.to_s unless options[:skip_relative_url_root]
- rewritten_url << (options[:trailing_slash] ? path.sub(/\?|\z/) { "/" + $& } : path)
- rewritten_url << "##{Rack::Utils.escape(options[:anchor].to_param.to_s)}" if options[:anchor]
-
- rewritten_url
- end
-
- protected
-
- def self.rewrite_authentication(options)
- if options[:user] && options[:password]
- "#{Rack::Utils.escape(options.delete(:user))}:#{Rack::Utils.escape(options.delete(:password))}@"
- else
- ""
- end
- end
-
- # Given a Hash of options, generates a route
- def process_path_options(options)
- options = options.symbolize_keys
- options.update(options[:params].symbolize_keys) if options[:params]
-
- if (overwrite = options.delete(:overwrite_params))
- options.update(@parameters.symbolize_keys)
- options.update(overwrite.symbolize_keys)
- end
-
- options
- end
-
- end
-end