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/caching/actions.rb68
-rw-r--r--actionpack/lib/action_controller/caching/pages.rb20
-rw-r--r--actionpack/lib/action_controller/metal/mime_responds.rb8
-rw-r--r--actionpack/lib/action_controller/metal/renderers.rb38
-rw-r--r--actionpack/lib/action_controller/metal/rendering.rb47
-rw-r--r--actionpack/lib/action_controller/metal/request_forgery_protection.rb10
-rw-r--r--actionpack/lib/action_controller/metal/url_for.rb4
-rw-r--r--actionpack/lib/action_controller/railtie.rb4
-rw-r--r--actionpack/lib/action_controller/railties/paths.rb8
-rw-r--r--actionpack/lib/action_controller/test_case.rb6
-rw-r--r--actionpack/lib/action_controller/vendor/html-scanner/html/sanitizer.rb4
11 files changed, 118 insertions, 99 deletions
diff --git a/actionpack/lib/action_controller/caching/actions.rb b/actionpack/lib/action_controller/caching/actions.rb
index d69d96b974..a4bac3caed 100644
--- a/actionpack/lib/action_controller/caching/actions.rb
+++ b/actionpack/lib/action_controller/caching/actions.rb
@@ -4,25 +4,26 @@ module ActionController #:nodoc:
module Caching
# Action caching is similar to page caching by the fact that the entire
# output of the response is cached, but unlike page caching, every
- # request still goes through the Action Pack. The key benefit
- # of this is that filters are run before the cache is served, which
- # allows for authentication and other restrictions on whether someone
- # is allowed to see the cache. Example:
+ # request still goes through Action Pack. The key benefit of this is
+ # that filters run before the cache is served, which allows for
+ # authentication and other restrictions on whether someone is allowed
+ # to execute such action. Example:
#
# class ListsController < ApplicationController
# before_filter :authenticate, :except => :public
+ #
# caches_page :public
- # caches_action :index, :show, :feed
+ # caches_action :index, :show
# end
#
- # In this example, the public action doesn't require authentication,
- # so it's possible to use the faster page caching method. But both
- # the show and feed action are to be shielded behind the authenticate
- # filter, so we need to implement those as action caches.
+ # In this example, the +public+ action doesn't require authentication
+ # so it's possible to use the faster page caching. On the other hand
+ # +index+ and +show+ require authentication. They can still be cached,
+ # but we need action caching for them.
#
- # Action caching internally uses the fragment caching and an around
- # filter to do the job. The fragment cache is named according to both
- # the current host and the path. So a page that is accessed at
+ # Action caching uses fragment caching internally and an around
+ # filter to do the job. The fragment cache is named according to
+ # the host and path of the request. A page that is accessed at
# <tt>http://david.example.com/lists/show/1</tt> will result in a fragment named
# <tt>david.example.com/lists/show/1</tt>. This allows the cacher to
# differentiate between <tt>david.example.com/lists/</tt> and
@@ -38,19 +39,23 @@ module ActionController #:nodoc:
# <tt>:action => 'list', :format => :xml</tt>.
#
# You can set modify the default action cache path by passing a
- # :cache_path option. This will be passed directly to
- # ActionCachePath.path_for. This is handy for actions with multiple
- # possible routes that should be cached differently. If a block is
- # given, it is called with the current controller instance.
+ # <tt>:cache_path</tt> option. This will be passed directly to
+ # <tt>ActionCachePath.path_for</tt>. This is handy for actions with
+ # multiple possible routes that should be cached differently. If a
+ # block is given, it is called with the current controller instance.
+ #
+ # And you can also use <tt>:if</tt> (or <tt>:unless</tt>) to pass a
+ # proc that specifies when the action should be cached.
#
- # And you can also use :if (or :unless) to pass a Proc that
- # specifies when the action should be cached.
+ # Finally, if you are using memcached, you can also pass <tt>:expires_in</tt>.
#
- # Finally, if you are using memcached, you can also pass :expires_in.
+ # The following example depicts some of the points made above:
#
# class ListsController < ApplicationController
# before_filter :authenticate, :except => :public
- # caches_page :public
+ #
+ # caches_page :public
+ #
# caches_action :index, :if => proc do |c|
# !c.request.format.json? # cache if is not a JSON request
# end
@@ -58,19 +63,28 @@ module ActionController #:nodoc:
# caches_action :show, :cache_path => { :project => 1 },
# :expires_in => 1.hour
#
- # caches_action :feed, :cache_path => proc do |controller|
- # if controller.params[:user_id]
- # controller.send(:user_list_url,
- # controller.params[:user_id], controller.params[:id])
+ # caches_action :feed, :cache_path => proc do |c|
+ # if c.params[:user_id]
+ # c.send(:user_list_url,
+ # c.params[:user_id], c.params[:id])
# else
- # controller.send(:list_url, controller.params[:id])
+ # c.send(:list_url, c.params[:id])
# end
# end
# end
#
- # If you pass :layout => false, it will only cache your action
- # content. It is useful when your layout has dynamic information.
+ # If you pass <tt>:layout => false</tt>, it will only cache your action
+ # content. That's useful when your layout has dynamic information.
+ #
+ # Warning: If the format of the request is determined by the Accept HTTP
+ # header the Content-Type of the cached response could be wrong because
+ # no information about the MIME type is stored in the cache key. So, if
+ # you first ask for MIME type M in the Accept header, a cache entry is
+ # created, and then perform a second resquest to the same resource asking
+ # for a different MIME type, you'd get the content cached for M.
#
+ # The <tt>:format</tt> parameter is taken into account though. The safest
+ # way to cache by MIME type is to pass the format in the route.
module Actions
extend ActiveSupport::Concern
diff --git a/actionpack/lib/action_controller/caching/pages.rb b/actionpack/lib/action_controller/caching/pages.rb
index 104157d0b1..3e57d2c236 100644
--- a/actionpack/lib/action_controller/caching/pages.rb
+++ b/actionpack/lib/action_controller/caching/pages.rb
@@ -70,9 +70,9 @@ module ActionController #:nodoc:
# Manually cache the +content+ in the key determined by +path+. Example:
# cache_page "I'm the cached content", "/lists/show"
- def cache_page(content, path)
+ def cache_page(content, path, extension = nil)
return unless perform_caching
- path = page_cache_path(path)
+ path = page_cache_path(path, extension)
instrument_page_cache :write_page, path do
FileUtils.makedirs(File.dirname(path))
@@ -97,14 +97,16 @@ module ActionController #:nodoc:
end
private
- def page_cache_file(path)
+ def page_cache_file(path, extension)
name = (path.empty? || path == "/") ? "/index" : URI.parser.unescape(path.chomp('/'))
- name << page_cache_extension unless (name.split('/').last || name).include? '.'
+ unless (name.split('/').last || name).include? '.'
+ name << (extension || self.page_cache_extension)
+ end
return name
end
- def page_cache_path(path)
- page_cache_directory + page_cache_file(path)
+ def page_cache_path(path, extension = nil)
+ page_cache_directory + page_cache_file(path, extension)
end
def instrument_page_cache(name, path)
@@ -145,7 +147,11 @@ module ActionController #:nodoc:
request.path
end
- self.class.cache_page(content || response.body, path)
+ if (type = Mime::LOOKUP[self.content_type]) && (type_symbol = type.symbol).present?
+ extension = ".#{type_symbol}"
+ end
+
+ self.class.cache_page(content || response.body, path, extension)
end
end
diff --git a/actionpack/lib/action_controller/metal/mime_responds.rb b/actionpack/lib/action_controller/metal/mime_responds.rb
index f7dd0dcb69..9ba37134b8 100644
--- a/actionpack/lib/action_controller/metal/mime_responds.rb
+++ b/actionpack/lib/action_controller/metal/mime_responds.rb
@@ -258,9 +258,8 @@ module ActionController #:nodoc:
# nil if :not_acceptable was sent to the client.
#
def retrieve_response_from_mimes(mimes=nil, &block)
- collector = Collector.new { default_render }
mimes ||= collect_mimes_from_class_level
- mimes.each { |mime| collector.send(mime) }
+ collector = Collector.new(mimes) { default_render }
block.call(collector) if block_given?
if format = request.negotiate_mime(collector.order)
@@ -277,8 +276,9 @@ module ActionController #:nodoc:
include AbstractController::Collector
attr_accessor :order
- def initialize(&block)
+ def initialize(mimes, &block)
@order, @responses, @default_response = [], {}, block
+ mimes.each { |mime| send(mime) }
end
def any(*args, &block)
@@ -291,7 +291,7 @@ module ActionController #:nodoc:
alias :all :any
def custom(mime_type, &block)
- mime_type = mime_type.is_a?(Mime::Type) ? mime_type : Mime::Type.lookup(mime_type.to_s)
+ mime_type = Mime::Type.lookup(mime_type.to_s) unless mime_type.is_a?(Mime::Type)
@order << mime_type
@responses[mime_type] ||= block
end
diff --git a/actionpack/lib/action_controller/metal/renderers.rb b/actionpack/lib/action_controller/metal/renderers.rb
index f9b226b7c9..d6f6ab1855 100644
--- a/actionpack/lib/action_controller/metal/renderers.rb
+++ b/actionpack/lib/action_controller/metal/renderers.rb
@@ -15,30 +15,12 @@ module ActionController
end
module ClassMethods
- def _write_render_options
- renderers = _renderers.map do |name, value|
- <<-RUBY_EVAL
- if options.key?(:#{name})
- _process_options(options)
- return _render_option_#{name}(options.delete(:#{name}), options)
- end
- RUBY_EVAL
- end
-
- class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
- def _handle_render_options(options)
- #{renderers.join}
- end
- RUBY_EVAL
- end
-
def use_renderers(*args)
new = _renderers.dup
args.each do |key|
new[key] = RENDERERS[key]
end
self._renderers = new.freeze
- _write_render_options
end
alias use_renderer use_renderers
end
@@ -47,31 +29,33 @@ module ActionController
_handle_render_options(options) || super
end
+ def _handle_render_options(options)
+ _renderers.each do |name, value|
+ if options.key?(name.to_sym)
+ _process_options(options)
+ return send("_render_option_#{name}", options.delete(name.to_sym), options)
+ end
+ end
+ nil
+ end
+
RENDERERS = {}
def self.add(key, &block)
define_method("_render_option_#{key}", &block)
RENDERERS[key] = block
- All._write_render_options
end
module All
extend ActiveSupport::Concern
include Renderers
- INCLUDED = []
included do
self._renderers = RENDERERS
- _write_render_options
- INCLUDED << self
- end
-
- def self._write_render_options
- INCLUDED.each(&:_write_render_options)
end
end
add :json do |json, options|
- json = json.to_json(options) unless json.respond_to?(:to_str)
+ json = json.to_json(options) unless json.kind_of?(String)
json = "#{options[:callback]}(#{json})" unless options[:callback].blank?
self.content_type ||= Mime::JSON
self.response_body = json
diff --git a/actionpack/lib/action_controller/metal/rendering.rb b/actionpack/lib/action_controller/metal/rendering.rb
index e524e546ad..14cc547dd0 100644
--- a/actionpack/lib/action_controller/metal/rendering.rb
+++ b/actionpack/lib/action_controller/metal/rendering.rb
@@ -20,36 +20,35 @@ module ActionController
private
- # Normalize arguments by catching blocks and setting them on :update.
- def _normalize_args(action=nil, options={}, &blk) #:nodoc:
- options = super
- options[:update] = blk if block_given?
- options
- end
-
- # Normalize both text and status options.
- def _normalize_options(options) #:nodoc:
- if options.key?(:text) && options[:text].respond_to?(:to_text)
- options[:text] = options[:text].to_text
- end
+ # Normalize arguments by catching blocks and setting them on :update.
+ def _normalize_args(action=nil, options={}, &blk) #:nodoc:
+ options = super
+ options[:update] = blk if block_given?
+ options
+ end
- if options[:status]
- options[:status] = Rack::Utils.status_code(options[:status])
- end
+ # Normalize both text and status options.
+ def _normalize_options(options) #:nodoc:
+ if options.key?(:text) && options[:text].respond_to?(:to_text)
+ options[:text] = options[:text].to_text
+ end
- super
+ if options[:status]
+ options[:status] = Rack::Utils.status_code(options[:status])
end
- # Process controller specific options, as status, content-type and location.
- def _process_options(options) #:nodoc:
- status, content_type, location = options.values_at(:status, :content_type, :location)
+ super
+ end
- self.status = status if status
- self.content_type = content_type if content_type
- self.headers["Location"] = url_for(location) if location
+ # Process controller specific options, as status, content-type and location.
+ def _process_options(options) #:nodoc:
+ status, content_type, location = options.values_at(:status, :content_type, :location)
- super
- end
+ self.status = status if status
+ self.content_type = content_type if content_type
+ self.headers["Location"] = url_for(location) if location
+ super
+ 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 02f577647e..148efbb081 100644
--- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb
+++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
@@ -53,9 +53,13 @@ module ActionController #:nodoc:
# class FooController < ApplicationController
# protect_from_forgery :except => :index
#
- # # you can disable csrf protection on controller-by-controller basis:
- # skip_before_filter :verify_authenticity_token
- # end
+ # You can disable csrf protection on controller-by-controller basis:
+ #
+ # skip_before_filter :verify_authenticity_token
+ #
+ # It can also be disabled for specific controller actions:
+ #
+ # skip_before_filter :verify_authenticity_token, :except => [:create]
#
# Valid Options:
#
diff --git a/actionpack/lib/action_controller/metal/url_for.rb b/actionpack/lib/action_controller/metal/url_for.rb
index 333eeaeffb..6fc0cf1fb8 100644
--- a/actionpack/lib/action_controller/metal/url_for.rb
+++ b/actionpack/lib/action_controller/metal/url_for.rb
@@ -6,7 +6,8 @@ module ActionController
def url_options
@_url_options ||= super.reverse_merge(
- :host => request.host_with_port,
+ :host => request.host,
+ :port => request.optional_port,
:protocol => request.protocol,
:_path_segments => request.symbolized_path_parameters
).freeze
@@ -20,5 +21,6 @@ module ActionController
@_url_options
end
end
+
end
end
diff --git a/actionpack/lib/action_controller/railtie.rb b/actionpack/lib/action_controller/railtie.rb
index c5a661f2b0..f0c29825ba 100644
--- a/actionpack/lib/action_controller/railtie.rb
+++ b/actionpack/lib/action_controller/railtie.rb
@@ -27,8 +27,8 @@ module ActionController
options.page_cache_directory ||= paths["public"].first
# make sure readers methods get compiled
- options.asset_path ||= nil
- options.asset_host ||= nil
+ options.asset_path ||= app.config.asset_path
+ options.asset_host ||= app.config.asset_host
ActiveSupport.on_load(:action_controller) do
include app.routes.mounted_helpers
diff --git a/actionpack/lib/action_controller/railties/paths.rb b/actionpack/lib/action_controller/railties/paths.rb
index 699c44c62c..dce3c2fe88 100644
--- a/actionpack/lib/action_controller/railties/paths.rb
+++ b/actionpack/lib/action_controller/railties/paths.rb
@@ -16,6 +16,14 @@ module ActionController
if klass.superclass == ActionController::Base && ActionController::Base.include_all_helpers
klass.helper :all
end
+
+ if app.config.serve_static_assets && namespace
+ paths = namespace._railtie.config.paths
+
+ klass.config.assets_dir = paths["public"].first
+ klass.config.javascripts_dir = paths["public/javascripts"].first
+ klass.config.stylesheets_dir = paths["public/stylesheets"].first
+ end
end
end
end
diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb
index 2b2f647d32..0f43527a56 100644
--- a/actionpack/lib/action_controller/test_case.rb
+++ b/actionpack/lib/action_controller/test_case.rb
@@ -1,6 +1,7 @@
require 'rack/session/abstract/id'
require 'active_support/core_ext/object/blank'
require 'active_support/core_ext/object/to_query'
+require 'active_support/core_ext/class/attribute'
module ActionController
module TemplateAssertions
@@ -325,11 +326,11 @@ module ActionController
def controller_class=(new_class)
prepare_controller_class(new_class) if new_class
- write_inheritable_attribute(:controller_class, new_class)
+ self._controller_class = new_class
end
def controller_class
- if current_controller_class = read_inheritable_attribute(:controller_class)
+ if current_controller_class = self._controller_class
current_controller_class
else
self.controller_class = determine_default_controller_class(name)
@@ -442,6 +443,7 @@ module ActionController
included do
include ActionController::TemplateAssertions
include ActionDispatch::Assertions
+ class_attribute :_controller_class
setup :setup_controller_request_and_response
end
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 dceddb9b80..3e5d23b5c1 100644
--- a/actionpack/lib/action_controller/vendor/html-scanner/html/sanitizer.rb
+++ b/actionpack/lib/action_controller/vendor/html-scanner/html/sanitizer.rb
@@ -1,5 +1,5 @@
require 'set'
-require 'active_support/core_ext/class/inheritable_attributes'
+require 'active_support/core_ext/class/attribute'
module HTML
class Sanitizer
@@ -60,7 +60,7 @@ module HTML
class WhiteListSanitizer < Sanitizer
[:protocol_separator, :uri_attributes, :allowed_attributes, :allowed_tags, :allowed_protocols, :bad_tags,
:allowed_css_properties, :allowed_css_keywords, :shorthand_css_properties].each do |attr|
- class_inheritable_accessor attr, :instance_writer => false
+ class_attribute attr, :instance_writer => false
end
# A regular expression of the valid characters used to separate protocols like