diff options
author | Emilio Tagua <miloops@gmail.com> | 2010-12-20 11:23:07 -0300 |
---|---|---|
committer | Emilio Tagua <miloops@gmail.com> | 2010-12-20 11:23:07 -0300 |
commit | 02fc6fbccdd3345e95592cc14e7855e2f1ea14b3 (patch) | |
tree | b26b91e2b2fad62ec382c9cee4ca2ac318f09257 /actionpack/lib/action_controller | |
parent | 2ba06b48defaca940e7c878724e2fb1c090eaa92 (diff) | |
parent | 0cbfd6c28d327304432f7d0c067662b5c1e41a78 (diff) | |
download | rails-02fc6fbccdd3345e95592cc14e7855e2f1ea14b3.tar.gz rails-02fc6fbccdd3345e95592cc14e7855e2f1ea14b3.tar.bz2 rails-02fc6fbccdd3345e95592cc14e7855e2f1ea14b3.zip |
Merge remote branch 'rails/master' into identity_map
Conflicts:
activerecord/lib/active_record/associations/association_proxy.rb
activerecord/lib/active_record/autosave_association.rb
activerecord/lib/active_record/base.rb
activerecord/lib/active_record/persistence.rb
Diffstat (limited to 'actionpack/lib/action_controller')
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 |