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 | |
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')
25 files changed, 359 insertions, 209 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index 248677688f..5a5c4b33f1 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,5 +1,56 @@ ## Rails 4.0.0 (unreleased) ## +* Failsafe exception returns text/plain. *Steve Klabnik* + +* Remove actionpack's rack-cache dependency and declare the + dependency in the Gemfile. + + *Guillermo Iguarán* + +* Rename internal variables on ActionController::TemplateAssertions to prevent + naming collisions. @partials, @templates and @layouts are now prefixed with an underscore. + Fix #7459 + + *Yves Senn* + +* `resource` and `resources` don't modify the passed options hash + Fix #7777 + + *Yves Senn* + +* Precompiled assets include aliases from foo.js to foo/index.js and vice versa. + + # Precompiles phone-<digest>.css and aliases phone/index.css to phone.css. + config.assets.precompile = [ 'phone.css' ] + + # Precompiles phone/index-<digest>.css and aliases phone.css to phone/index.css. + config.assets.precompile = [ 'phone/index.css' ] + + # Both of these work with either precompile thanks to their aliases. + <%= stylesheet_link_tag 'phone', media: 'all' %> + <%= stylesheet_link_tag 'phone/index', media: 'all' %> + + *Jeremy Kemper* + +* `assert_template` is no more passing with what ever string that matches + with the template name. + + Before when we have a template `/layout/hello.html.erb`, `assert_template` + was passing with any string that matches. This behavior allowed false + positive like: + + assert_template "layout" + assert_template "out/hello" + + Now it only passes with: + + assert_template "layout/hello" + assert_template "hello" + + Fixes #3849. + + *Hugolnx* + * `image_tag` will set the same width and height for image if numerical value passed to `size` option. @@ -44,9 +95,8 @@ *Luiz Felipe Garcia Pereira* -* Sprockets integration has been extracted from Action Pack and the `sprockets-rails` - gem should be added to Gemfile (under the assets group) in order to use Rails asset - pipeline in future versions of Rails. +* Sprockets integration has been extracted from Action Pack to the `sprockets-rails` + gem. `rails` gem is depending on `sprockets-rails` by default. *Guillermo Iguaran* diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec index fd09d3b55b..7d292ac17c 100644 --- a/actionpack/actionpack.gemspec +++ b/actionpack/actionpack.gemspec @@ -18,7 +18,6 @@ Gem::Specification.new do |s| s.requirements << 'none' s.add_dependency('activesupport', version) - s.add_dependency('rack-cache', '~> 1.2') s.add_dependency('builder', '~> 3.1.0') s.add_dependency('rack', '~> 1.4.1') s.add_dependency('rack-test', '~> 0.6.1') 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 diff --git a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb index ab740a0190..402f29cd76 100644 --- a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb +++ b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb @@ -15,11 +15,11 @@ module ActionDispatch # If any exception happens inside the exceptions app, this middleware # catches the exceptions and returns a FAILSAFE_RESPONSE. class ShowExceptions - FAILSAFE_RESPONSE = [500, {'Content-Type' => 'text/html'}, - ["<html><body><h1>500 Internal Server Error</h1>" << + FAILSAFE_RESPONSE = [500, { 'Content-Type' => 'text/plain' }, + ["500 Internal Server Error\n" << "If you are the administrator of this website, then please read this web " << "application's log file and/or the web server's log file to find out what " << - "went wrong.</body></html>"]] + "went wrong."]] def initialize(app, exceptions_app) @app = app diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 49afa01d25..c5cf413c8f 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -1038,7 +1038,7 @@ module ActionDispatch # === Options # Takes same options as +resources+. def resource(*resources, &block) - options = resources.extract_options! + options = resources.extract_options!.dup if apply_common_behavior_for(:resource, resources, options, &block) return self @@ -1204,7 +1204,7 @@ module ActionDispatch # # resource actions are at /admin/posts. # resources :posts, :path => "admin/posts" def resources(*resources, &block) - options = resources.extract_options! + options = resources.extract_options!.dup if apply_common_behavior_for(:resources, resources, options, &block) return self diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb index 27ba57ff58..5b5fc84e90 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb @@ -369,9 +369,9 @@ module ActionView # <tt>:size</tt> will be ignored if the value is not in the correct format. # # image_tag("icon") - # # => <img src="/assets/icon" alt="Icon" /> + # # => <img alt="Icon" src="/assets/icon" /> # image_tag("icon.png") - # # => <img src="/assets/icon.png" alt="Icon" /> + # # => <img alt="Icon" src="/assets/icon.png" /> # image_tag("icon.png", :size => "16x10", :alt => "Edit Entry") # # => <img src="/assets/icon.png" width="16" height="10" alt="Edit Entry" /> # image_tag("/icons/icon.gif", :size => "16") diff --git a/actionpack/lib/action_view/log_subscriber.rb b/actionpack/lib/action_view/log_subscriber.rb index cc3a871576..fd9a543e0a 100644 --- a/actionpack/lib/action_view/log_subscriber.rb +++ b/actionpack/lib/action_view/log_subscriber.rb @@ -3,10 +3,13 @@ module ActionView # # Provides functionality so that Rails can output logs from Action View. class LogSubscriber < ActiveSupport::LogSubscriber + VIEWS_PATTERN = /^app\/views\//.freeze + def render_template(event) + return unless logger.info? message = " Rendered #{from_rails_root(event.payload[:identifier])}" message << " within #{from_rails_root(event.payload[:layout])}" if event.payload[:layout] - message << (" (%.1fms)" % event.duration) + message << " (#{event.duration.round(1)}ms)" info(message) end alias :render_partial :render_template @@ -19,7 +22,7 @@ module ActionView protected def from_rails_root(string) - string.sub("#{Rails.root}/", "").sub(/^app\/views\//, "") + string.sub("#{Rails.root}/", "").sub(VIEWS_PATTERN, "") end end end diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb index 04073c73cc..5434b3421e 100644 --- a/actionpack/lib/action_view/test_case.rb +++ b/actionpack/lib/action_view/test_case.rb @@ -196,16 +196,17 @@ module ActionView :@_result, :@_routes, :@controller, - :@layouts, + :@_layouts, :@locals, :@method_name, :@output_buffer, - :@partials, + :@_partials, :@passed, :@rendered, :@request, :@routes, - :@templates, + :@tagged_logger, + :@_templates, :@options, :@test_passed, :@view, diff --git a/actionpack/test/controller/action_pack_assertions_test.rb b/actionpack/test/controller/action_pack_assertions_test.rb index 4ab5d92a2b..ca542eb7e2 100644 --- a/actionpack/test/controller/action_pack_assertions_test.rb +++ b/actionpack/test/controller/action_pack_assertions_test.rb @@ -7,6 +7,7 @@ class ActionPackAssertionsController < ActionController::Base def nothing() head :ok end def hello_world() render :template => "test/hello_world"; end + def hello_repeating_in_path() render :template => "test/hello/hello"; end def hello_xml_world() render :template => "test/hello_xml_world"; end @@ -464,6 +465,20 @@ class AssertTemplateTest < ActionController::TestCase end end + def test_fails_with_incorrect_string_that_matches + get :hello_world + assert_raise(ActiveSupport::TestCase::Assertion) do + assert_template 'est/he' + end + end + + def test_fails_with_repeated_name_in_path + get :hello_repeating_in_path + assert_raise(ActiveSupport::TestCase::Assertion) do + assert_template 'test/hello' + end + end + def test_fails_with_incorrect_symbol get :hello_world assert_raise(ActiveSupport::TestCase::Assertion) do @@ -471,6 +486,13 @@ class AssertTemplateTest < ActionController::TestCase end end + def test_fails_with_incorrect_symbol_that_matches + get :hello_world + assert_raise(ActiveSupport::TestCase::Assertion) do + assert_template :"est/he" + end + end + def test_fails_with_wrong_layout get :render_with_layout assert_raise(ActiveSupport::TestCase::Assertion) do diff --git a/actionpack/test/controller/caching_test.rb b/actionpack/test/controller/caching_test.rb index 2c3511f6a0..620479cb0c 100644 --- a/actionpack/test/controller/caching_test.rb +++ b/actionpack/test/controller/caching_test.rb @@ -5,6 +5,43 @@ require 'active_record_unit' CACHE_DIR = 'test_cache' # Don't change '/../temp/' cavalierly or you might hose something you don't want hosed FILE_STORE_PATH = File.join(File.dirname(__FILE__), '/../temp/', CACHE_DIR) + +class CachingMetalController < ActionController::Metal + abstract! + + include ActionController::Caching + + self.page_cache_directory = FILE_STORE_PATH + self.cache_store = :file_store, FILE_STORE_PATH +end + +class PageCachingMetalTestController < CachingMetalController + caches_page :ok + + def ok + self.response_body = 'ok' + end +end + +class PageCachingMetalTest < ActionController::TestCase + tests PageCachingMetalTestController + + def setup + FileUtils.rm_rf(File.dirname(FILE_STORE_PATH)) + FileUtils.mkdir_p(FILE_STORE_PATH) + end + + def teardown + FileUtils.rm_rf(File.dirname(FILE_STORE_PATH)) + end + + def test_should_cache_get_with_ok_status + get :ok + assert_response :ok + assert File.exist?("#{FILE_STORE_PATH}/page_caching_metal_test/ok.html"), 'get with ok status should have been cached' + end +end + ActionController::Base.page_cache_directory = FILE_STORE_PATH class CachingController < ActionController::Base @@ -862,7 +899,7 @@ CACHED get :html_fragment_cached_with_partial assert_response :success assert_match(/Old fragment caching in a partial/, @response.body) - + assert_match("Old fragment caching in a partial", @store.read("views/test.host/functional_caching/html_fragment_cached_with_partial/#{template_digest("functional_caching/_partial", "html")}")) end @@ -872,7 +909,7 @@ CACHED assert_response :success assert_match(/Some inline content/, @response.body) assert_match(/Some cached content/, @response.body) - assert_match("Some cached content", + assert_match("Some cached content", @store.read("views/test.host/functional_caching/inline_fragment_cached/#{template_digest("functional_caching/inline_fragment_cached", "html")}")) end @@ -883,7 +920,7 @@ CACHED assert_equal expected_body, @response.body - assert_equal "<p>ERB</p>", + assert_equal "<p>ERB</p>", @store.read("views/test.host/functional_caching/formatted_fragment_cached/#{template_digest("functional_caching/formatted_fragment_cached", "html")}") end @@ -897,7 +934,7 @@ CACHED assert_equal " <p>Builder</p>\n", @store.read("views/test.host/functional_caching/formatted_fragment_cached/#{template_digest("functional_caching/formatted_fragment_cached", "xml")}") end - + private def template_digest(name, format) ActionView::Digestor.digest(name, format, @controller.lookup_context) @@ -949,5 +986,5 @@ class CacheHelperOutputBufferTest < ActionController::TestCase cache_helper.send :fragment_for, 'Test fragment name', 'Test fragment', &Proc.new{ nil } end end - end + diff --git a/actionpack/test/controller/show_exceptions_test.rb b/actionpack/test/controller/show_exceptions_test.rb index 351b9c4cfa..ab1bd0e3b6 100644 --- a/actionpack/test/controller/show_exceptions_test.rb +++ b/actionpack/test/controller/show_exceptions_test.rb @@ -93,4 +93,20 @@ module ShowExceptions assert_equal 'text/html', response.content_type.to_s end end + + class ShowFailsafeExceptionsTest < ActionDispatch::IntegrationTest + def test_render_failsafe_exception + @app = ShowExceptionsOverridenController.action(:boom) + @exceptions_app = @app.instance_variable_get(:@exceptions_app) + @app.instance_variable_set(:@exceptions_app, nil) + $stderr = StringIO.new + + get '/', {}, 'HTTP_ACCEPT' => 'text/json' + assert_response :internal_server_error + assert_equal 'text/plain', response.content_type.to_s + + @app.instance_variable_set(:@exceptions_app, @exceptions_app) + $stderr = STDERR + end + end end diff --git a/actionpack/test/controller/spec_type_test.rb b/actionpack/test/controller/spec_type_test.rb index caeb0fd4dd..13be8a3405 100644 --- a/actionpack/test/controller/spec_type_test.rb +++ b/actionpack/test/controller/spec_type_test.rb @@ -3,7 +3,7 @@ require "abstract_unit" class ApplicationController < ActionController::Base; end class ModelsController < ApplicationController; end -class SpecTypeTest < ActiveSupport::TestCase +class ActionControllerSpecTypeTest < ActiveSupport::TestCase def assert_controller actual assert_equal ActionController::TestCase, actual end diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index 4e83ad16d7..93d89f7568 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -1124,6 +1124,26 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest assert_equal '/sheep/1/_it', _it_sheep_path(1) end + def test_resource_does_not_modify_passed_options + options = {:id => /.+?/, :format => /json|xml/} + self.class.stub_controllers do |routes| + routes.draw do + resource :user, options + end + end + assert_equal({:id => /.+?/, :format => /json|xml/}, options) + end + + def test_resources_does_not_modify_passed_options + options = {:id => /.+?/, :format => /json|xml/} + self.class.stub_controllers do |routes| + routes.draw do + resources :users, options + end + end + assert_equal({:id => /.+?/, :format => /json|xml/}, options) + end + def test_path_names get '/pt/projetos' assert_equal 'projects#index', @response.body diff --git a/actionpack/test/dispatch/session/cache_store_test.rb b/actionpack/test/dispatch/session/cache_store_test.rb index a74e165826..b8479e8836 100644 --- a/actionpack/test/dispatch/session/cache_store_test.rb +++ b/actionpack/test/dispatch/session/cache_store_test.rb @@ -1,4 +1,5 @@ require 'abstract_unit' +require 'fixtures/session_autoload_test/session_autoload_test/foo' class CacheStoreTest < ActionDispatch::IntegrationTest class TestController < ActionController::Base diff --git a/actionpack/test/fixtures/test/hello/hello.erb b/actionpack/test/fixtures/test/hello/hello.erb new file mode 100644 index 0000000000..6769dd60bd --- /dev/null +++ b/actionpack/test/fixtures/test/hello/hello.erb @@ -0,0 +1 @@ +Hello world!
\ No newline at end of file diff --git a/actionpack/test/metal/caching_test.rb b/actionpack/test/metal/caching_test.rb deleted file mode 100644 index a2b6763754..0000000000 --- a/actionpack/test/metal/caching_test.rb +++ /dev/null @@ -1,32 +0,0 @@ -require 'abstract_unit' - -CACHE_DIR = 'test_cache' -# Don't change '/../temp/' cavalierly or you might hose something you don't want hosed -FILE_STORE_PATH = File.join(File.dirname(__FILE__), '/../temp/', CACHE_DIR) - -class CachingController < ActionController::Metal - abstract! - - include ActionController::Caching - - self.page_cache_directory = FILE_STORE_PATH - self.cache_store = :file_store, FILE_STORE_PATH -end - -class PageCachingTestController < CachingController - caches_page :ok - - def ok - self.response_body = "ok" - end -end - -class PageCachingTest < ActionController::TestCase - tests PageCachingTestController - - def test_should_cache_get_with_ok_status - get :ok - assert_response :ok - assert File.exist?("#{FILE_STORE_PATH}/page_caching_test/ok.html"), "get with ok status should have been cached" - end -end diff --git a/actionpack/test/template/spec_type_test.rb b/actionpack/test/template/spec_type_test.rb index b35985d5f9..08a7bdf81d 100644 --- a/actionpack/test/template/spec_type_test.rb +++ b/actionpack/test/template/spec_type_test.rb @@ -1,6 +1,6 @@ require 'abstract_unit' -class SpecTypeTest < ActiveSupport::TestCase +class ActionViewSpecTypeTest < ActiveSupport::TestCase def assert_view actual assert_equal ActionView::TestCase, actual end |