Permalink
Browse files

Merge branch 'master' of git@github.com:lifo/docrails

  • Loading branch information...
2 parents a325010 + 303919c commit 4a53eb8a79e3e0535ba19e6da38370a542ce4961 @radar radar committed Oct 22, 2008
Showing 301 changed files with 20,621 additions and 641 deletions.
View
@@ -5,12 +5,13 @@ activerecord/doc
actionpack/doc
actionmailer/doc
activesupport/doc
-railties/doc
activeresource/pkg
activerecord/pkg
actionpack/pkg
actionmailer/pkg
activesupport/pkg
railties/pkg
railties/test/500.html
+railties/doc/guides/html/images
+railties/doc/guides/html/stylesheets
*.rbc
View
@@ -1,5 +1,39 @@
*Edge*
+* Added stale? and fresh_when methods to provide a layer of abstraction above request.fresh? and friends [DHH]. Example:
+
+ class ArticlesController < ApplicationController
+ def show_with_respond_to_block
+ @article = Article.find(params[:id])
+
+
+ # If the request sends headers that differs from the options provided to stale?, then
+ # the request is indeed stale and the respond_to block is triggered (and the options
+ # to the stale? call is set on the response).
+ #
+ # If the request headers match, then the request is fresh and the respond_to block is
+ # not triggered. Instead the default render will occur, which will check the last-modified
+ # and etag headers and conclude that it only needs to send a "304 Not Modified" instead
+ # of rendering the template.
+ if stale?(:last_modified => @article.published_at.utc, :etag => @article)
+ respond_to do |wants|
+ # normal response processing
+ end
+ end
+ end
+
+ def show_with_implied_render
+ @article = Article.find(params[:id])
+
+ # Sets the response headers and checks them against the request, if the request is stale
+ # (i.e. no match of either etag or last-modified), then the default render of the template happens.
+ # If the request is fresh, then the default render will return a "304 Not Modified"
+ # instead of rendering the template.
+ fresh_when(:last_modified => @article.published_at.utc, :etag => @article)
+ end
+ end
+
+
* Added inline builder yield to atom_feed_helper tags where appropriate [Sam Ruby]. Example:
entry.summary :type => 'xhtml' do |xhtml|
@@ -965,22 +965,6 @@ def head(*args)
render :nothing => true, :status => status
end
- # Sets the Last-Modified response header. Returns 304 Not Modified if the
- # If-Modified-Since request header is <= last modified.
- def last_modified!(utc_time)
- response.last_modified= utc_time
- if request.if_modified_since && request.if_modified_since <= utc_time
- head(:not_modified)
- end
- end
-
- # Sets the ETag response header. Returns 304 Not Modified if the
- # If-None-Match request header matches.
- def etag!(etag)
- response.etag = etag
- head(:not_modified) if response.etag == request.if_none_match
- end
-
# Clears the rendered results, allowing for another render to be performed.
def erase_render_results #:nodoc:
response.body = nil
@@ -1090,6 +1074,51 @@ def redirect_to_full_url(url, status)
@performed_redirect = true
end
+ # 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 "304 Not Modified" is sent.
+ #
+ # Example:
+ #
+ # def show
+ # @article = Article.find(params[:id])
+ #
+ # if stale?(:etag => @article, :last_modified => @article.created_at.utc)
+ # @statistics = @article.really_expensive_call
+ # respond_to do |format|
+ # # all the supported formats
+ # end
+ # end
+ # end
+ def stale?(options)
+ fresh_when(options)
+ !request.fresh?(response)
+ end
+
+ # Sets the etag, last_modified, or both on the response and renders a
+ # "304 Not Modified" response if the request is already fresh.
+ #
+ # Example:
+ #
+ # def show
+ # @article = Article.find(params[:id])
+ # fresh_when(:etag => @article, :last_modified => @article.created_at.utc)
+ # end
+ #
+ # This will render the show template if the request isn't sending a matching etag or
+ # If-Modified-Since header and just a "304 Not Modified" response if there's a match.
+ def fresh_when(options)
+ options.assert_valid_keys(:etag, :last_modified)
+
+ response.etag = options[:etag] if options[:etag]
+ response.last_modified = options[:last_modified] if options[:last_modified]
+
+ if request.fresh?(response)
+ head :not_modified
+ end
+ end
+
# Sets a HTTP 1.1 Cache-Control header. Defaults to issuing a "private" instruction, so that
# intermediate caches shouldn't cache the response.
#
@@ -26,32 +26,6 @@ module Caching
#
# expire_fragment(:controller => "topics", :action => "list", :action_suffix => "all_topics")
module Fragments
- def self.included(base) #:nodoc:
- base.class_eval do
- class << self
- def fragment_cache_store=(store_option) #:nodoc:
- ActiveSupport::Deprecation.warn('The fragment_cache_store= method is now use cache_store=')
- self.cache_store = store_option
- end
-
- def fragment_cache_store #:nodoc:
- ActiveSupport::Deprecation.warn('The fragment_cache_store method is now use cache_store')
- cache_store
- end
- end
-
- def fragment_cache_store=(store_option) #:nodoc:
- ActiveSupport::Deprecation.warn('The fragment_cache_store= method is now use cache_store=')
- self.cache_store = store_option
- end
-
- def fragment_cache_store #:nodoc:
- ActiveSupport::Deprecation.warn('The fragment_cache_store method is now use cache_store')
- cache_store
- end
- end
- end
-
# Given a key (as described in <tt>expire_fragment</tt>), returns a key suitable for use in reading,
# writing, or expiring a cached fragment. If the key is a hash, the generated key is the return
# value of url_for on that hash (without the protocol). All keys are prefixed with "views/" and uses
@@ -39,7 +39,7 @@ def dispatch(cgi = nil, session_options = CgiRequest::DEFAULT_SESSION_OPTIONS, o
# Add a preparation callback. Preparation callbacks are run before every
# request in development mode, and before the first request in production
# mode.
- #
+ #
# An optional identifier may be supplied for the callback. If provided,
# to_prepare may be called again with the same identifier to replace the
# existing callback. Passing an identifier is a suggested practice if the
@@ -144,6 +144,7 @@ def reload_application
Routing::Routes.reload
ActionController::Base.view_paths.reload!
+ ActionView::Helpers::AssetTagHelper::AssetTag::Cache.clear
end
# Cleanup the application by clearing out loaded classes so they can
@@ -120,9 +120,19 @@ def etag_matches?(etag)
end
# Check response freshness (Last-Modified and ETag) against request
- # If-Modified-Since and If-None-Match conditions.
+ # If-Modified-Since and If-None-Match conditions. If both headers are
+ # supplied, both must match, or the request is not considered fresh.
def fresh?(response)
- not_modified?(response.last_modified) || etag_matches?(response.etag)
+ case
+ when if_modified_since && if_none_match
+ not_modified?(response.last_modified) && etag_matches?(response.etag)
+ when if_modified_since
+ not_modified?(response.last_modified)
+ when if_none_match
+ etag_matches?(response.etag)
+ else
+ false
+ end
end
# Returns the Mime type for the \format used in the request.
@@ -114,8 +114,8 @@ def etag=(etag)
def redirect(url, status)
self.status = status
- self.location = url
- self.body = "<html><body>You are being <a href=\"#{url}\">redirected</a>.</body></html>"
+ self.location = url.gsub(/[\r\n]/, '')
+ self.body = "<html><body>You are being <a href=\"#{CGI.escapeHTML(url)}\">redirected</a>.</body></html>"
end
def sending_file?
@@ -172,18 +172,6 @@ class << self
delegate :logger, :to => 'ActionController::Base'
end
- def self.cache_template_loading=(*args)
- ActiveSupport::Deprecation.warn(
- "config.action_view.cache_template_loading option has been deprecated" +
- "and has no effect. Please remove it from your config files.", caller)
- end
-
- def self.cache_template_extensions=(*args)
- ActiveSupport::Deprecation.warn(
- "config.action_view.cache_template_extensions option has been" +
- "deprecated and has no effect. Please remove it from your config files.", caller)
- end
-
# Templates that are exempt from layouts
@@exempt_from_layout = Set.new([/\.rjs$/])
@@ -259,10 +247,6 @@ def render(options = {}, local_assigns = {}, &block) #:nodoc:
if options[:layout]
_render_with_layout(options, local_assigns, &block)
elsif options[:file]
- if options[:use_full_path]
- ActiveSupport::Deprecation.warn("use_full_path option has been deprecated and has no affect.", caller)
- end
-
_pick_template(options[:file]).render_template(self, options[:locals])
elsif options[:partial]
render_partial(options)
@@ -26,9 +26,17 @@ def teardown
end
def test_clears_dependencies_after_dispatch_if_in_loading_mode
- ActionController::Routing::Routes.expects(:reload).once
ActiveSupport::Dependencies.expects(:clear).once
+ dispatch(@output, false)
+ end
+
+ def test_reloads_routes_before_dispatch_if_in_loading_mode
+ ActionController::Routing::Routes.expects(:reload).once
+ dispatch(@output, false)
+ end
+ def test_clears_asset_tag_cache_before_dispatch_if_in_loading_mode
+ ActionView::Helpers::AssetTagHelper::AssetTag::Cache.expects(:clear).once
dispatch(@output, false)
end
@@ -30,24 +30,18 @@ def hello_world
end
def conditional_hello
- response.last_modified = Time.now.utc.beginning_of_day
- response.etag = [:foo, 123]
-
- if request.fresh?(response)
- head :not_modified
- else
+ if stale?(:last_modified => Time.now.utc.beginning_of_day, :etag => [:foo, 123])
render :action => 'hello_world'
end
end
-
+
def conditional_hello_with_bangs
render :action => 'hello_world'
end
before_filter :handle_last_modified_and_etags, :only=>:conditional_hello_with_bangs
def handle_last_modified_and_etags
- last_modified! Time.now.utc.beginning_of_day
- etag! [:foo, 123]
+ fresh_when(:last_modified => Time.now.utc.beginning_of_day, :etag => [ :foo, 123 ])
end
def render_hello_world
@@ -248,7 +242,7 @@ def default_render
if @alternate_default_render
@alternate_default_render.call
else
- render
+ super
end
end
@@ -1422,6 +1416,13 @@ def test_request_not_modified
assert_equal @last_modified, @response.headers['Last-Modified']
end
+ def test_request_not_modified_but_etag_differs
+ @request.if_modified_since = @last_modified
+ @request.if_none_match = "234"
+ get :conditional_hello
+ assert_response :success
+ end
+
def test_request_modified
@request.if_modified_since = 'Thu, 16 Jul 2008 00:00:00 GMT'
get :conditional_hello
@@ -1445,7 +1446,7 @@ def test_request_with_bang_obeys_last_modified
def test_last_modified_works_with_less_than_too
@request.if_modified_since = 5.years.ago.httpdate
get :conditional_hello_with_bangs
- assert_response :not_modified
+ assert_response :success
end
end
@@ -326,8 +326,8 @@ def include?(record)
exists?(record)
end
- def proxy_respond_to?(method)
- super || @reflection.klass.respond_to?(method)
+ def proxy_respond_to?(method, include_private = false)
+ super || @reflection.klass.respond_to?(method, include_private)
end
protected
@@ -1081,8 +1081,14 @@ def test_association_proxy_transaction_method_starts_transaction_in_association_
end
def test_sending_new_to_association_proxy_should_have_same_effect_as_calling_new
- clients_assoc = companies(:first_firm).clients
- assert_equal clients_assoc.new.attributes, clients_assoc.send(:new).attributes
+ client_association = companies(:first_firm).clients
+ assert_equal client_association.new.attributes, client_association.send(:new).attributes
+ end
+
+ def test_respond_to_private_class_methods
+ client_association = companies(:first_firm).clients
+ assert !client_association.respond_to?(:private_method)
+ assert client_association.respond_to?(:private_method, true)
end
end
@@ -112,6 +112,14 @@ def ruby_type
def rating?
query_attribute :rating
end
+
+ class << self
+ private
+
+ def private_method
+ "darkness"
+ end
+ end
end
View
@@ -1,5 +1,9 @@
*Edge*
+* TimeWithZone#freeze: preload instance variables so that we can actually freeze [Geoff Buesing]
+
+* Fix Brasilia timezone #1180 [Marcus Derencius, Kane]
+
* Time#advance recognizes fractional days and weeks. Deprecate Durations of fractional months and years #970 [Tom Lea]
* Add ActiveSupport::Rescuable module abstracting ActionController::Base rescue_from features. [Norbert Crombach, Pratik]
@@ -59,7 +59,3 @@
require 'active_support/rescuable'
I18n.load_path << File.dirname(__FILE__) + '/active_support/locale/en-US.yml'
-
-Inflector = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('Inflector', 'ActiveSupport::Inflector')
-Dependencies = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('Dependencies', 'ActiveSupport::Dependencies')
-TimeZone = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('TimeZone', 'ActiveSupport::TimeZone')
Oops, something went wrong.

0 comments on commit 4a53eb8

Please sign in to comment.