diff options
author | Ryan Garver <ragarver@gmail.com> | 2012-10-02 10:37:27 -0700 |
---|---|---|
committer | Ryan Garver <ragarver@gmail.com> | 2012-10-02 10:37:27 -0700 |
commit | 4cb50a3f571234b1202f9a0dffe39b445ecf807d (patch) | |
tree | 13780082c3974bc480cf35722cabf8788beed3ab /actionpack/lib/action_controller | |
parent | 3fdb7126110caad3f3db4c2b44ffc365b51c34eb (diff) | |
parent | df08271f9c044b7614d70baf4b818f1a79f4a6e1 (diff) | |
download | rails-4cb50a3f571234b1202f9a0dffe39b445ecf807d.tar.gz rails-4cb50a3f571234b1202f9a0dffe39b445ecf807d.tar.bz2 rails-4cb50a3f571234b1202f9a0dffe39b445ecf807d.zip |
Merge branch 'master' into feature/public-fragment_name_with_digest
Diffstat (limited to 'actionpack/lib/action_controller')
-rw-r--r-- | actionpack/lib/action_controller/caching.rb | 10 | ||||
-rw-r--r-- | actionpack/lib/action_controller/caching/actions.rb | 26 | ||||
-rw-r--r-- | actionpack/lib/action_controller/caching/fragments.rb | 36 | ||||
-rw-r--r-- | actionpack/lib/action_controller/caching/pages.rb | 91 | ||||
-rw-r--r-- | actionpack/lib/action_controller/caching/sweeping.rb | 27 | ||||
-rw-r--r-- | actionpack/lib/action_controller/log_subscriber.rb | 17 | ||||
-rw-r--r-- | actionpack/lib/action_controller/metal/conditional_get.rb | 58 | ||||
-rw-r--r-- | actionpack/lib/action_controller/metal/strong_parameters.rb | 20 | ||||
-rw-r--r-- | actionpack/lib/action_controller/test_case.rb | 55 |
9 files changed, 186 insertions, 154 deletions
diff --git a/actionpack/lib/action_controller/caching.rb b/actionpack/lib/action_controller/caching.rb index be29099fbe..fc27a0774b 100644 --- a/actionpack/lib/action_controller/caching.rb +++ b/actionpack/lib/action_controller/caching.rb @@ -23,10 +23,10 @@ module ActionController #:nodoc: # Configuration examples (MemoryStore is the default): # # config.action_controller.cache_store = :memory_store - # config.action_controller.cache_store = :file_store, "/path/to/cache/directory" - # config.action_controller.cache_store = :mem_cache_store, "localhost" - # config.action_controller.cache_store = :mem_cache_store, Memcached::Rails.new("localhost:11211") - # config.action_controller.cache_store = MyOwnStore.new("parameter") + # config.action_controller.cache_store = :file_store, '/path/to/cache/directory' + # config.action_controller.cache_store = :mem_cache_store, 'localhost' + # config.action_controller.cache_store = :mem_cache_store, Memcached::Rails.new('localhost:11211') + # config.action_controller.cache_store = MyOwnStore.new('parameter') module Caching extend ActiveSupport::Concern extend ActiveSupport::Autoload @@ -73,7 +73,7 @@ module ActionController #:nodoc: end protected - # Convenience accessor + # Convenience accessor. def cache(key, options = {}, &block) if cache_configured? cache_store.fetch(ActiveSupport::Cache.expand_cache_key(key, :controller), options, &block) diff --git a/actionpack/lib/action_controller/caching/actions.rb b/actionpack/lib/action_controller/caching/actions.rb index eb3aa05a25..bf16fe267c 100644 --- a/actionpack/lib/action_controller/caching/actions.rb +++ b/actionpack/lib/action_controller/caching/actions.rb @@ -1,16 +1,16 @@ require 'set' -module ActionController #:nodoc: +module ActionController 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 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: + # to execute such action. # # class ListsController < ApplicationController - # before_filter :authenticate, :except => :public + # before_filter :authenticate, except: :public # # caches_page :public # caches_action :index, :show @@ -35,8 +35,8 @@ module ActionController #:nodoc: # <tt>http://david.example.com/lists.xml</tt> # are treated like separate requests and so are cached separately. # Keep in mind when expiring an action cache that - # <tt>:action => 'lists'</tt> is not the same as - # <tt>:action => 'list', :format => :xml</tt>. + # <tt>action: 'lists'</tt> is not the same as + # <tt>action: 'list', format: :xml</tt>. # # You can modify the default action cache path by passing a # <tt>:cache_path</tt> option. This will be passed directly to @@ -53,18 +53,18 @@ module ActionController #:nodoc: # The following example depicts some of the points made above: # # class ListsController < ApplicationController - # before_filter :authenticate, :except => :public + # before_filter :authenticate, except: :public # # caches_page :public # - # caches_action :index, :if => Proc.new do + # caches_action :index, if: Proc.new do # !request.format.json? # cache if is not a JSON request # end # - # caches_action :show, :cache_path => { :project => 1 }, - # :expires_in => 1.hour + # caches_action :show, cache_path: { project: 1 }, + # expires_in: 1.hour # - # caches_action :feed, :cache_path => Proc.new do + # caches_action :feed, cache_path: Proc.new do # if params[:user_id] # user_list_url(params[:user_id, params[:id]) # else @@ -73,7 +73,7 @@ module ActionController #:nodoc: # end # end # - # If you pass <tt>:layout => false</tt>, it will only cache your action + # 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 @@ -162,9 +162,9 @@ module ActionController #:nodoc: class ActionCachePath attr_reader :path, :extension - # If +infer_extension+ is true, the cache path extension is looked up from the request's + # If +infer_extension+ is +true+, the cache path extension is looked up from the request's # path and format. This is desirable when reading and writing the cache, but not when - # expiring the cache - expire_action should expire the same files regardless of the + # expiring the cache - +expire_action+ should expire the same files regardless of the # request format. def initialize(controller, options = {}, infer_extension = true) if infer_extension diff --git a/actionpack/lib/action_controller/caching/fragments.rb b/actionpack/lib/action_controller/caching/fragments.rb index 9c77b0ccf4..879d5fdd94 100644 --- a/actionpack/lib/action_controller/caching/fragments.rb +++ b/actionpack/lib/action_controller/caching/fragments.rb @@ -1,29 +1,29 @@ -module ActionController #:nodoc: +module ActionController module Caching - # Fragment caching is used for caching various blocks within + # Fragment caching is used for caching various blocks within # views without caching the entire action as a whole. This is - # useful when certain elements of an action change frequently or - # depend on complicated state while other parts rarely change or + # useful when certain elements of an action change frequently or + # depend on complicated state while other parts rarely change or # can be shared amongst multiple parties. The caching is done using - # the <tt>cache</tt> helper available in the Action View. See + # the +cache+ helper available in the Action View. See # ActionView::Helpers::CacheHelper for more information. # # While it's strongly recommended that you use key-based cache # expiration (see links in CacheHelper for more information), # it is also possible to manually expire caches. For example: # - # expire_fragment("name_of_cache") + # expire_fragment('name_of_cache') module Fragments - # Given a key (as described in <tt>expire_fragment</tt>), returns - # a key suitable for use in reading, writing, or expiring a + # Given a key (as described in +expire_fragment+), returns + # a key suitable for use in reading, writing, or expiring a # cached fragment. All keys are prefixed with <tt>views/</tt> and uses # ActiveSupport::Cache.expand_cache_key for the expansion. def fragment_cache_key(key) ActiveSupport::Cache.expand_cache_key(key.is_a?(Hash) ? url_for(key).split("://").last : key, :views) end - # Writes <tt>content</tt> to the location signified by - # <tt>key</tt> (see <tt>expire_fragment</tt> for acceptable formats). + # Writes +content+ to the location signified by + # +key+ (see +expire_fragment+ for acceptable formats). def write_fragment(key, content, options = nil) return content unless cache_configured? @@ -35,8 +35,8 @@ module ActionController #:nodoc: content end - # Reads a cached fragment from the location signified by <tt>key</tt> - # (see <tt>expire_fragment</tt> for acceptable formats). + # Reads a cached fragment from the location signified by +key+ + # (see +expire_fragment+ for acceptable formats). def read_fragment(key, options = nil) return unless cache_configured? @@ -47,8 +47,8 @@ module ActionController #:nodoc: end end - # Check if a cached fragment from the location signified by - # <tt>key</tt> exists (see <tt>expire_fragment</tt> for acceptable formats) + # Check if a cached fragment from the location signified by + # +key+ exists (see +expire_fragment+ for acceptable formats). def fragment_exist?(key, options = nil) return unless cache_configured? key = fragment_cache_key(key) @@ -65,7 +65,7 @@ module ActionController #:nodoc: # * String - This would normally take the form of a path, like # <tt>pages/45/notes</tt>. # * Hash - Treated as an implicit call to +url_for+, like - # <tt>{:controller => "pages", :action => "notes", :id => 45}</tt> + # <tt>{ controller: 'pages', action: 'notes', id: 45}</tt> # * Regexp - Will remove any fragment that matches, so # <tt>%r{pages/\d*/notes}</tt> might remove all notes. Make sure you # don't use anchors in the regex (<tt>^</tt> or <tt>$</tt>) because @@ -74,8 +74,8 @@ module ActionController #:nodoc: # only supported on caches that can iterate over all keys (unlike # memcached). # - # +options+ is passed through to the cache store's <tt>delete</tt> - # method (or <tt>delete_matched</tt>, for Regexp keys.) + # +options+ is passed through to the cache store's +delete+ + # method (or <tt>delete_matched</tt>, for Regexp keys). def expire_fragment(key, options = nil) return unless cache_configured? key = fragment_cache_key(key) unless key.is_a?(Regexp) @@ -89,7 +89,7 @@ module ActionController #:nodoc: end end - def instrument_fragment_cache(name, key) + def instrument_fragment_cache(name, key) # :nodoc: ActiveSupport::Notifications.instrument("#{name}.action_controller", :key => key){ yield } end end diff --git a/actionpack/lib/action_controller/caching/pages.rb b/actionpack/lib/action_controller/caching/pages.rb index 73b8cd383c..3cf8d965ff 100644 --- a/actionpack/lib/action_controller/caching/pages.rb +++ b/actionpack/lib/action_controller/caching/pages.rb @@ -1,60 +1,72 @@ require 'fileutils' require 'active_support/core_ext/class/attribute_accessors' -module ActionController #:nodoc: +module ActionController module Caching - # Page caching is an approach to caching where the entire action output of is stored as a HTML file that the web server - # can serve without going through Action Pack. This is the fastest way to cache your content as opposed to going dynamically - # through the process of generating the content. Unfortunately, this incredible speed-up is only available to stateless pages - # where all visitors are treated the same. Content management systems -- including weblogs and wikis -- have many pages that are - # a great fit for this approach, but account-based systems where people log in and manipulate their own data are often less - # likely candidates. + # Page caching is an approach to caching where the entire action output of is + # stored as a HTML file that the web server can serve without going through + # Action Pack. This is the fastest way to cache your content as opposed to going + # dynamically through the process of generating the content. Unfortunately, this + # incredible speed-up is only available to stateless pages where all visitors are + # treated the same. Content management systems -- including weblogs and wikis -- + # have many pages that are a great fit for this approach, but account-based systems + # where people log in and manipulate their own data are often less likely candidates. # - # Specifying which actions to cache is done through the <tt>caches_page</tt> class method: + # Specifying which actions to cache is done through the +caches_page+ class method: # # class WeblogController < ActionController::Base # caches_page :show, :new # end # - # This will generate cache files such as <tt>weblog/show/5.html</tt> and <tt>weblog/new.html</tt>, which match the URLs used - # that would normally trigger dynamic page generation. Page caching works by configuring a web server to first check for the - # existence of files on disk, and to serve them directly when found, without passing the request through to Action Pack. - # This is much faster than handling the full dynamic request in the usual way. + # This will generate cache files such as <tt>weblog/show/5.html</tt> and + # <tt>weblog/new.html</tt>, which match the URLs used that would normally trigger + # dynamic page generation. Page caching works by configuring a web server to first + # check for the existence of files on disk, and to serve them directly when found, + # without passing the request through to Action Pack. This is much faster than + # handling the full dynamic request in the usual way. # - # Expiration of the cache is handled by deleting the cached file, which results in a lazy regeneration approach where the cache - # is not restored before another hit is made against it. The API for doing so mimics the options from +url_for+ and friends: + # Expiration of the cache is handled by deleting the cached file, which results + # in a lazy regeneration approach where the cache is not restored before another + # hit is made against it. The API for doing so mimics the options from +url_for+ and friends: # # class WeblogController < ActionController::Base # def update # List.update(params[:list][:id], params[:list]) - # expire_page :action => "show", :id => params[:list][:id] - # redirect_to :action => "show", :id => params[:list][:id] + # expire_page action: 'show', id: params[:list][:id] + # redirect_to action: 'show', id: params[:list][:id] # end # end # - # Additionally, you can expire caches using Sweepers that act on changes in the model to determine when a cache is supposed to be - # expired. + # 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 extend ActiveSupport::Concern included do - # 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. + # 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. class_attribute :page_cache_directory self.page_cache_directory ||= '' - # 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. + # 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. class_attribute :page_cache_extension self.page_cache_extension ||= '.html' - # The compression used for gzip. If false (default), the page is not compressed. - # If can be a symbol showing the ZLib compression method, for example, :best_compression - # or :best_speed or an integer configuring the compression level. + # The compression used for gzip. If +false+ (default), the page is not compressed. + # If can be a symbol showing the ZLib compression method, for example, <tt>:best_compression</tt> + # or <tt>:best_speed</tt> or an integer configuring the compression level. class_attribute :page_cache_compression self.page_cache_compression ||= false end @@ -62,7 +74,7 @@ module ActionController #:nodoc: module ClassMethods # Expires the page that was cached with the +path+ as a key. # - # expire_page "/lists/show" + # expire_page '/lists/show' def expire_page(path) return unless perform_caching path = page_cache_path(path) @@ -75,7 +87,7 @@ module ActionController #:nodoc: # Manually cache the +content+ in the key determined by +path+. # - # cache_page "I'm the cached content", "/lists/show" + # cache_page "I'm the cached content", '/lists/show' def cache_page(content, path, extension = nil, gzip = Zlib::BEST_COMPRESSION) return unless perform_caching path = page_cache_path(path, extension) @@ -90,19 +102,19 @@ module ActionController #:nodoc: end # Caches the +actions+ using the page-caching approach that'll store - # the cache in a path within the page_cache_directory that + # the cache in a path within the +page_cache_directory+ that # matches the triggering url. # - # You can also pass a :gzip option to override the class configuration one. + # You can also pass a <tt>:gzip</tt> option to override the class configuration one. # # # cache the index action # caches_page :index # # # cache the index action except for JSON requests - # caches_page :index, :if => Proc.new { !request.format.json? } + # caches_page :index, if: Proc.new { !request.format.json? } # # # don't gzip images - # caches_page :image, :gzip => false + # caches_page :image, gzip: false def caches_page(*actions) return unless perform_caching options = actions.extract_options! @@ -144,7 +156,7 @@ module ActionController #:nodoc: # Expires the page that was cached with the +options+ as a key. # - # expire_page :controller => "lists", :action => "show" + # expire_page controller: 'lists', action: 'show' def expire_page(options = {}) return unless self.class.perform_caching @@ -161,10 +173,11 @@ module ActionController #:nodoc: end end - # Manually cache the +content+ in the key determined by +options+. If no content is provided, the contents of response.body is used. - # If no options are provided, the url of the current request being handled is used. + # Manually cache the +content+ in the key determined by +options+. If no content is provided, + # the contents of response.body is used. If no options are provided, the url of the current + # request being handled is used. # - # cache_page "I'm the cached content", :controller => "lists", :action => "show" + # cache_page "I'm the cached content", controller: 'lists', action: 'show' def cache_page(content = nil, options = nil, gzip = Zlib::BEST_COMPRESSION) return unless self.class.perform_caching && caching_allowed? diff --git a/actionpack/lib/action_controller/caching/sweeping.rb b/actionpack/lib/action_controller/caching/sweeping.rb index 271d5f06b8..317ac74b40 100644 --- a/actionpack/lib/action_controller/caching/sweeping.rb +++ b/actionpack/lib/action_controller/caching/sweeping.rb @@ -1,38 +1,41 @@ -module ActionController #:nodoc: +module ActionController module Caching - # Sweepers are the terminators of the caching world and responsible for expiring caches when Active Record objects change. - # They do this by being half-observers, half-filters and implementing callbacks for both roles. A Sweeper example: + # Sweepers are the terminators of the caching world and responsible for expiring + # caches when Active Record objects change. They do this by being half-observers, + # half-filters and implementing callbacks for both roles. # # class ListSweeper < ActionController::Caching::Sweeper # observe List, Item # # def after_save(record) # list = record.is_a?(List) ? record : record.list - # expire_page(:controller => "lists", :action => %w( show public feed ), :id => list.id) - # expire_action(:controller => "lists", :action => "all") - # list.shares.each { |share| expire_page(:controller => "lists", :action => "show", :id => share.url_key) } + # expire_page(controller: 'lists', action: %w( show public feed ), id: list.id) + # expire_action(controller: 'lists', action: 'all') + # list.shares.each { |share| expire_page(controller: 'lists', action: 'show', id: share.url_key) } # end # end # - # The sweeper is assigned in the controllers that wish to have its job performed using the <tt>cache_sweeper</tt> class method: + # The sweeper is assigned in the controllers that wish to have its job performed using + # the +cache_sweeper+ class method: # # class ListsController < ApplicationController # caches_action :index, :show, :public, :feed - # cache_sweeper :list_sweeper, :only => [ :edit, :destroy, :share ] + # cache_sweeper :list_sweeper, only: [ :edit, :destroy, :share ] # end # # In the example above, four actions are cached and three actions are responsible for expiring those caches. # - # You can also name an explicit class in the declaration of a sweeper, which is needed if the sweeper is in a module: + # You can also name an explicit class in the declaration of a sweeper, which is needed + # if the sweeper is in a module: # # class ListsController < ApplicationController # caches_action :index, :show, :public, :feed - # cache_sweeper OpenBar::Sweeper, :only => [ :edit, :destroy, :share ] + # cache_sweeper OpenBar::Sweeper, only: [ :edit, :destroy, :share ] # end module Sweeping extend ActiveSupport::Concern - module ClassMethods #:nodoc: + module ClassMethods # :nodoc: def cache_sweeper(*sweepers) configuration = sweepers.extract_options! @@ -51,7 +54,7 @@ module ActionController #:nodoc: end if defined?(ActiveRecord) and defined?(ActiveRecord::Observer) - class Sweeper < ActiveRecord::Observer #:nodoc: + class Sweeper < ActiveRecord::Observer # :nodoc: attr_accessor :controller def initialize(*args) diff --git a/actionpack/lib/action_controller/log_subscriber.rb b/actionpack/lib/action_controller/log_subscriber.rb index f41d1bb4b9..3d274e7dd7 100644 --- a/actionpack/lib/action_controller/log_subscriber.rb +++ b/actionpack/lib/action_controller/log_subscriber.rb @@ -4,6 +4,8 @@ module ActionController INTERNAL_PARAMS = %w(controller action format _method only_path) def start_processing(event) + return unless logger.info? + payload = event.payload params = payload[:params].except(*INTERNAL_PARAMS) format = payload[:format] @@ -14,6 +16,8 @@ module ActionController end def process_action(event) + return unless logger.info? + payload = event.payload additions = ActionController::Base.log_process_action(payload) @@ -22,35 +26,36 @@ module ActionController exception_class_name = payload[:exception].first status = ActionDispatch::ExceptionWrapper.status_code_for_exception(exception_class_name) end - message = "Completed #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]} in %.0fms" % event.duration + message = "Completed #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]} in #{event.duration.round}ms" message << " (#{additions.join(" | ")})" unless additions.blank? info(message) end def halted_callback(event) - info "Filter chain halted as #{event.payload[:filter]} rendered or redirected" + info("Filter chain halted as #{event.payload[:filter]} rendered or redirected") end def send_file(event) - info("Sent file %s (%.1fms)" % [event.payload[:path], event.duration]) + info("Sent file #{event.payload[:path]} (#{event.duration.round(1)}ms)") end def redirect_to(event) - info "Redirected to #{event.payload[:location]}" + info("Redirected to #{event.payload[:location]}") end def send_data(event) - info("Sent data %s (%.1fms)" % [event.payload[:filename], event.duration]) + info("Sent data #{event.payload[:filename]} (#{event.duration.round(1)}ms)") end %w(write_fragment read_fragment exist_fragment? expire_fragment expire_page write_page).each do |method| class_eval <<-METHOD, __FILE__, __LINE__ + 1 def #{method}(event) + return unless logger.info? key_or_path = event.payload[:key] || event.payload[:path] human_name = #{method.to_s.humanize.inspect} - info("\#{human_name} \#{key_or_path} \#{"(%.1fms)" % event.duration}") + info("\#{human_name} \#{key_or_path} (\#{event.duration.round(1)}ms)") end METHOD end diff --git a/actionpack/lib/action_controller/metal/conditional_get.rb b/actionpack/lib/action_controller/metal/conditional_get.rb index 12ef68ff26..3f37a6a618 100644 --- a/actionpack/lib/action_controller/metal/conditional_get.rb +++ b/actionpack/lib/action_controller/metal/conditional_get.rb @@ -18,8 +18,6 @@ module ActionController # may want to add the current user id to be part of the etag to prevent authorized displaying # of cached pages. # - # === Example - # # class InvoicesController < ApplicationController # etag { current_user.try :id } # @@ -34,25 +32,28 @@ module ActionController end end - # Sets the etag, last_modified, or both on the response and renders a + # Sets the etag, +last_modified+, or both on the response and renders a # <tt>304 Not Modified</tt> response if the request is already fresh. # - # Parameters: - # * <tt>:etag</tt> - # * <tt>:last_modified</tt> - # * <tt>:public</tt> By default the Cache-Control header is private, set this to true if you want your application to be cachable by other devices (proxy caches). + # === Parameters: + # + # * <tt>:etag</tt>. + # * <tt>:last_modified</tt>. + # * <tt>:public</tt> By default the Cache-Control header is private, set this to + # +true+ if you want your application to be cachable by other devices (proxy caches). # - # Example: + # === Example: # # def show # @article = Article.find(params[:id]) - # fresh_when(:etag => @article, :last_modified => @article.created_at, :public => true) + # fresh_when(etag: @article, last_modified: @article.created_at, public: true) # end # # This will render the show template if the request isn't sending a matching etag or # If-Modified-Since header and just a <tt>304 Not Modified</tt> response if there's a match. # - # You can also just pass a record where last_modified will be set by calling updated_at and the etag by passing the object itself. Example: + # You can also just pass a record where +last_modified+ will be set by calling + # +updated_at+ and the etag by passing the object itself. # # def show # @article = Article.find(params[:id]) @@ -81,22 +82,24 @@ module ActionController head :not_modified if request.fresh?(response) end - # Sets the etag and/or last_modified on the response and checks it against + # Sets the +etag+ and/or +last_modified+ on the response and checks it against # the client request. If the request doesn't match the options provided, the # request is considered stale and should be generated from scratch. Otherwise, # it's fresh and we don't need to generate anything and a reply of <tt>304 Not Modified</tt> is sent. # - # Parameters: - # * <tt>:etag</tt> - # * <tt>:last_modified</tt> - # * <tt>:public</tt> By default the Cache-Control header is private, set this to true if you want your application to be cachable by other devices (proxy caches). + # === Parameters: + # + # * <tt>:etag</tt>. + # * <tt>:last_modified</tt>. + # * <tt>:public</tt> By default the Cache-Control header is private, set this to + # +true+ if you want your application to be cachable by other devices (proxy caches). # - # Example: + # === Example: # # def show # @article = Article.find(params[:id]) # - # if stale?(:etag => @article, :last_modified => @article.created_at) + # if stale?(etag: @article, last_modified: @article.created_at) # @statistics = @article.really_expensive_call # respond_to do |format| # # all the supported formats @@ -104,7 +107,8 @@ module ActionController # end # end # - # You can also just pass a record where last_modified will be set by calling updated_at and the etag by passing the object itself. Example: + # You can also just pass a record where +last_modified+ will be set by calling + # updated_at and the etag by passing the object itself. # # def show # @article = Article.find(params[:id]) @@ -122,7 +126,7 @@ module ActionController # def show # @article = Article.find(params[:id]) # - # if stale?(@article, :public => true) + # if stale?(@article, public: true) # @statistics = @article.really_expensive_call # respond_to do |format| # # all the supported formats @@ -134,18 +138,18 @@ module ActionController !request.fresh?(response) end - # Sets a HTTP 1.1 Cache-Control header. Defaults to issuing a <tt>private</tt> instruction, so that - # intermediate caches must not cache the response. + # Sets a HTTP 1.1 Cache-Control header. Defaults to issuing a +private+ + # instruction, so that intermediate caches must not cache the response. # # expires_in 20.minutes - # expires_in 3.hours, :public => true - # expires_in 3.hours, :public => true, :must_revalidate => true + # expires_in 3.hours, public: true + # expires_in 3.hours, public: true, must_revalidate: true # # This method will overwrite an existing Cache-Control header. # See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html for more possibilities. # # The method will also ensure a HTTP Date header for client compatibility. - def expires_in(seconds, options = {}) #:doc: + def expires_in(seconds, options = {}) response.cache_control.merge!( :max_age => seconds, :public => options.delete(:public), @@ -157,9 +161,9 @@ module ActionController response.date = Time.now unless response.date? end - # Sets a HTTP 1.1 Cache-Control header of <tt>no-cache</tt> so no caching should occur by the browser or - # intermediate caches (like caching proxy servers). - def expires_now #:doc: + # Sets a HTTP 1.1 Cache-Control header of <tt>no-cache</tt> so no caching should + # occur by the browser or intermediate caches (like caching proxy servers). + def expires_now response.cache_control.replace(:no_cache => true) end diff --git a/actionpack/lib/action_controller/metal/strong_parameters.rb b/actionpack/lib/action_controller/metal/strong_parameters.rb index 55cc62a15e..c9a81e4866 100644 --- a/actionpack/lib/action_controller/metal/strong_parameters.rb +++ b/actionpack/lib/action_controller/metal/strong_parameters.rb @@ -7,15 +7,15 @@ module ActionController # # params = ActionController::Parameters.new(a: {}) # params.fetch(:b) - # # => ActionController::ParameterMissing: key not found: b + # # => ActionController::ParameterMissing: param not found: b # params.require(:a) - # # => ActionController::ParameterMissing: key not found: a + # # => ActionController::ParameterMissing: param not found: a class ParameterMissing < KeyError attr_reader :param # :nodoc: def initialize(param) # :nodoc: @param = param - super("key not found: #{param}") + super("param not found: #{param}") end end @@ -124,10 +124,10 @@ module ActionController # # => {"name"=>"Francesco"} # # ActionController::Parameters.new(person: nil).require(:person) - # # => ActionController::ParameterMissing: key not found: person + # # => ActionController::ParameterMissing: param not found: person # # ActionController::Parameters.new(person: {}).require(:person) - # # => ActionController::ParameterMissing: key not found: person + # # => ActionController::ParameterMissing: param not found: person def require(key) self[key].presence || raise(ParameterMissing.new(key)) end @@ -160,7 +160,7 @@ module ActionController # } # }) # - # permitted = params.permit(person: [ :name, { pets: [ :name ] } ]) + # permitted = params.permit(person: [ :name, { pets: :name } ]) # permitted.permitted? # => true # permitted[:person][:name] # => "Francesco" # permitted[:person][:age] # => nil @@ -212,7 +212,7 @@ module ActionController # # params = ActionController::Parameters.new(person: { name: 'Francesco' }) # params.fetch(:person) # => {"name"=>"Francesco"} - # params.fetch(:none) # => ActionController::ParameterMissing: key not found: none + # params.fetch(:none) # => ActionController::ParameterMissing: param not found: none # params.fetch(:none, 'Francesco') # => "Francesco" # params.fetch(:none) { 'Francesco' } # => "Francesco" def fetch(key, *args) @@ -269,7 +269,7 @@ module ActionController end end - # == Strong Parameters + # == Strong \Parameters # # It provides an interface for protecting attributes from end-user # assignment. This makes Action Controller parameters forbidden @@ -290,9 +290,9 @@ module ActionController # end # # # This will pass with flying colors as long as there's a person key in the - # # parameters, otherwise it'll raise a ActionController::MissingParameter + # # parameters, otherwise it'll raise an ActionController::MissingParameter # # exception, which will get caught by ActionController::Base and turned - # # into that 400 Bad Request reply. + # # into a 400 Bad Request reply. # def update # redirect_to current_account.people.find(params[:id]).tap { |person| # person.update_attributes!(person_params) diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb index 0caeef3192..3af378173a 100644 --- a/actionpack/lib/action_controller/test_case.rb +++ b/actionpack/lib/action_controller/test_case.rb @@ -12,16 +12,16 @@ module ActionController end def setup_subscriptions - @partials = Hash.new(0) - @templates = Hash.new(0) - @layouts = Hash.new(0) + @_partials = Hash.new(0) + @_templates = Hash.new(0) + @_layouts = Hash.new(0) ActiveSupport::Notifications.subscribe("render_template.action_view") do |name, start, finish, id, payload| path = payload[:layout] if path - @layouts[path] += 1 + @_layouts[path] += 1 if path =~ /^layouts\/(.*)/ - @layouts[$1] += 1 + @_layouts[$1] += 1 end end end @@ -32,11 +32,11 @@ module ActionController partial = path =~ /^.*\/_[^\/]*$/ if partial - @partials[path] += 1 - @partials[path.split("/").last] += 1 + @_partials[path] += 1 + @_partials[path.split("/").last] += 1 end - @templates[path] += 1 + @_templates[path] += 1 end end @@ -46,9 +46,9 @@ module ActionController end def process(*args) - @partials = Hash.new(0) - @templates = Hash.new(0) - @layouts = Hash.new(0) + @_partials = Hash.new(0) + @_templates = Hash.new(0) + @_layouts = Hash.new(0) super end @@ -86,31 +86,38 @@ module ActionController response.body case options - when NilClass, String, Symbol, Regexp + when NilClass, Regexp, String, Symbol options = options.to_s if Symbol === options - rendered = @templates + rendered = @_templates msg = message || sprintf("expecting <%s> but rendering with <%s>", options.inspect, rendered.keys) matches_template = - if options + case options + when String + rendered.any? do |t, num| + options_splited = options.split(File::SEPARATOR) + t_splited = t.split(File::SEPARATOR) + t_splited.last(options_splited.size) == options_splited + end + when Regexp rendered.any? { |t,num| t.match(options) } - else - @templates.blank? + when NilClass + rendered.blank? end assert matches_template, msg when Hash if options.key?(:layout) expected_layout = options[:layout] msg = message || sprintf("expecting layout <%s> but action rendered <%s>", - expected_layout, @layouts.keys) + expected_layout, @_layouts.keys) case expected_layout when String, Symbol - assert_includes @layouts.keys, expected_layout.to_s, msg + assert_includes @_layouts.keys, expected_layout.to_s, msg when Regexp - assert(@layouts.keys.any? {|l| l =~ expected_layout }, msg) + assert(@_layouts.keys.any? {|l| l =~ expected_layout }, msg) when nil, false - assert(@layouts.empty?, msg) + assert(@_layouts.empty?, msg) end end @@ -121,17 +128,17 @@ module ActionController assert_equal(v, actual_locals[k]) end elsif expected_count = options[:count] - actual_count = @partials[expected_partial] + actual_count = @_partials[expected_partial] msg = message || sprintf("expecting %s to be rendered %s time(s) but rendered %s time(s)", expected_partial, expected_count, actual_count) assert(actual_count == expected_count.to_i, msg) else msg = message || sprintf("expecting partial <%s> but action rendered <%s>", - options[:partial], @partials.keys) - assert_includes @partials, expected_partial, msg + options[:partial], @_partials.keys) + assert_includes @_partials, expected_partial, msg end elsif options.key?(:partial) - assert @partials.empty?, + assert @_partials.empty?, "Expected no partials to be rendered" end else |