Upgrade to Rails 2.2.0

As a side benefit, fix an (non-user-visible) bug in display_s5().
Also fixed a bug where removing orphaned pages did not expire cached summary pages.
This commit is contained in:
Jacques Distler 2008-10-27 01:47:01 -05:00
parent 39348c65c2
commit 7600aef48b
827 changed files with 123652 additions and 11027 deletions

View file

@ -252,7 +252,7 @@ module ActionController #:nodoc:
#
# def do_something
# redirect_to(:action => "elsewhere") and return if monkeys.nil?
# render :action => "overthere" # won't be called unless monkeys is nil
# render :action => "overthere" # won't be called if monkeys is nil
# end
#
class Base
@ -260,10 +260,11 @@ module ActionController #:nodoc:
include StatusCodes
cattr_reader :protected_instance_variables
# Controller specific instance variables which will not be accessible inside views.
@@protected_view_variables = %w(@assigns @performed_redirect @performed_render @variables_added @request_origin @url @parent_controller
@action_name @before_filter_chain_aborted @action_cache_path @_session @_cookies @_headers @_params
@_flash @_response)
@@protected_instance_variables = %w(@assigns @performed_redirect @performed_render @variables_added @request_origin @url @parent_controller
@action_name @before_filter_chain_aborted @action_cache_path @_session @_cookies @_headers @_params
@_flash @_response)
# Prepends all the URL-generating helpers from AssetHelper. This makes it possible to easily move javascripts, stylesheets,
# and images to a dedicated asset server away from the main web server. Example:
@ -283,10 +284,9 @@ module ActionController #:nodoc:
@@debug_routes = true
cattr_accessor :debug_routes
# Indicates to Mongrel or Webrick whether to allow concurrent action
# processing. Your controller actions and any other code they call must
# also behave well when called from concurrent threads. Turned off by
# default.
# Indicates whether to allow concurrent action processing. Your
# controller actions and any other code they call must also behave well
# when called from concurrent threads. Turned off by default.
@@allow_concurrency = false
cattr_accessor :allow_concurrency
@ -347,10 +347,29 @@ module ActionController #:nodoc:
cattr_accessor :optimise_named_routes
self.optimise_named_routes = true
# Indicates whether the response format should be determined by examining the Accept HTTP header,
# or by using the simpler params + ajax rules.
#
# If this is set to +true+ (the default) then +respond_to+ and +Request#format+ will take the Accept
# header into account. If it is set to false then the request format will be determined solely
# by examining params[:format]. If params format is missing, the format will be either HTML or
# Javascript depending on whether the request is an AJAX request.
cattr_accessor :use_accept_header
self.use_accept_header = true
# Controls whether request forgergy protection is turned on or not. Turned off by default only in test mode.
class_inheritable_accessor :allow_forgery_protection
self.allow_forgery_protection = true
# If you are deploying to a subdirectory, you will need to set
# <tt>config.action_controller.relative_url_root</tt>
# This defaults to ENV['RAILS_RELATIVE_URL_ROOT']
cattr_writer :relative_url_root
def self.relative_url_root
@@relative_url_root || ENV['RAILS_RELATIVE_URL_ROOT']
end
# Holds the request object that's primarily used to get environment variables through access like
# <tt>request.env["REQUEST_URI"]</tt>.
attr_internal :request
@ -373,16 +392,9 @@ module ActionController #:nodoc:
# directive. Values should always be specified as strings.
attr_internal :headers
# Holds the hash of variables that are passed on to the template class to be made available to the view. This hash
# is generated by taking a snapshot of all the instance variables in the current scope just before a template is rendered.
attr_accessor :assigns
# Returns the name of the action this controller is processing.
attr_accessor :action_name
# Templates that are exempt from layouts
@@exempt_from_layout = Set.new([/\.rjs$/])
class << self
# Factory for the standard create, process loop where the controller is discarded after processing.
def process(request, response) #:nodoc:
@ -408,28 +420,27 @@ module ActionController #:nodoc:
# By default, all methods defined in ActionController::Base and included modules are hidden.
# More methods can be hidden using <tt>hide_actions</tt>.
def hidden_actions
unless read_inheritable_attribute(:hidden_actions)
write_inheritable_attribute(:hidden_actions, ActionController::Base.public_instance_methods.map(&:to_s))
end
read_inheritable_attribute(:hidden_actions)
read_inheritable_attribute(:hidden_actions) || write_inheritable_attribute(:hidden_actions, [])
end
# Hide each of the given methods from being callable as actions.
def hide_action(*names)
write_inheritable_attribute(:hidden_actions, hidden_actions | names.map(&:to_s))
write_inheritable_attribute(:hidden_actions, hidden_actions | names.map { |name| name.to_s })
end
## View load paths determine the bases from which template references can be made. So a call to
## render("test/template") will be looked up in the view load paths array and the closest match will be
## returned.
# View load paths determine the bases from which template references can be made. So a call to
# render("test/template") will be looked up in the view load paths array and the closest match will be
# returned.
def view_paths
@view_paths || superclass.view_paths
if defined? @view_paths
@view_paths
else
superclass.view_paths
end
end
def view_paths=(value)
@view_paths = value
ActionView::TemplateFinder.process_view_paths(value)
@view_paths = ActionView::Base.process_view_paths(value) if value
end
# Adds a view_path to the front of the view_paths array.
@ -440,9 +451,8 @@ module ActionController #:nodoc:
# ArticleController.prepend_view_path(["views/default", "views/custom"])
#
def prepend_view_path(path)
@view_paths = superclass.view_paths.dup if @view_paths.nil?
view_paths.unshift(*path)
ActionView::TemplateFinder.process_view_paths(path)
@view_paths = superclass.view_paths.dup if !defined?(@view_paths) || @view_paths.nil?
@view_paths.unshift(*path)
end
# Adds a view_path to the end of the view_paths array.
@ -454,8 +464,7 @@ module ActionController #:nodoc:
#
def append_view_path(path)
@view_paths = superclass.view_paths.dup if @view_paths.nil?
view_paths.push(*path)
ActionView::TemplateFinder.process_view_paths(path)
@view_paths.push(*path)
end
# Replace sensitive parameter data from the request log.
@ -507,38 +516,34 @@ module ActionController #:nodoc:
protected :filter_parameters
end
# Don't render layouts for templates with the given extensions.
def exempt_from_layout(*extensions)
regexps = extensions.collect do |extension|
extension.is_a?(Regexp) ? extension : /\.#{Regexp.escape(extension.to_s)}$/
end
@@exempt_from_layout.merge regexps
end
delegate :exempt_from_layout, :to => 'ActionView::Base'
end
public
# Extracts the action_name from the request parameters and performs that action.
def process(request, response, method = :perform_action, *arguments) #:nodoc:
response.request = request
initialize_template_class(response)
assign_shortcuts(request, response)
initialize_current_url
assign_names
forget_variables_added_to_assigns
log_processing
send(method, *arguments)
assign_default_content_type_and_charset
response.request = request
response.prepare! unless component_request?
response
send_response
ensure
process_cleanup
end
# Returns a URL that has been rewritten according to the options hash and the defined Routes.
# (For doing a complete redirect, use redirect_to).
def send_response
response.prepare! unless component_request?
response
end
# Returns a URL that has been rewritten according to the options hash and the defined routes.
# (For doing a complete redirect, use +redirect_to+).
#
# <tt>url_for</tt> is used to:
#
@ -578,7 +583,15 @@ module ActionController #:nodoc:
# missing values in the current request's parameters. Routes attempts to guess when a value should and should not be
# taken from the defaults. There are a few simple rules on how this is performed:
#
# * If the controller name begins with a slash, no defaults are used: <tt>url_for :controller => '/home'</tt>
# * If the controller name begins with a slash no defaults are used:
#
# url_for :controller => '/home'
#
# In particular, a leading slash ensures no namespace is assumed. Thus,
# while <tt>url_for :controller => 'users'</tt> may resolve to
# <tt>Admin::UsersController</tt> if the current controller lives under
# that module, <tt>url_for :controller => '/users'</tt> ensures you link
# to <tt>::UsersController</tt> no matter what.
# * If the controller changes, the action will default to index unless provided
#
# The final rule is applied while the URL is being generated and is best illustrated by an example. Let us consider the
@ -648,11 +661,11 @@ module ActionController #:nodoc:
# View load paths for controller.
def view_paths
@template.finder.view_paths
@template.view_paths
end
def view_paths=(value)
@template.finder.view_paths = value # Mutex needed
@template.view_paths = ActionView::Base.process_view_paths(value)
end
# Adds a view_path to the front of the view_paths array.
@ -662,7 +675,7 @@ module ActionController #:nodoc:
# self.prepend_view_path(["views/default", "views/custom"])
#
def prepend_view_path(path)
@template.finder.prepend_view_path(path) # Mutex needed
@template.view_paths.unshift(*path)
end
# Adds a view_path to the end of the view_paths array.
@ -672,7 +685,7 @@ module ActionController #:nodoc:
# self.append_view_path(["views/default", "views/custom"])
#
def append_view_path(path)
@template.finder.append_view_path(path) # Mutex needed
@template.view_paths.push(*path)
end
protected
@ -713,6 +726,9 @@ module ActionController #:nodoc:
# # builds the complete response.
# render :partial => "person", :collection => @winners
#
# # Renders a collection of partials but with a custom local variable name
# render :partial => "admin_person", :collection => @winners, :as => :person
#
# # Renders the same collection of partials, but also renders the
# # person_divider partial between each person partial.
# render :partial => "person", :collection => @winners, :spacer_template => "person_divider"
@ -760,9 +776,6 @@ module ActionController #:nodoc:
# render :file => "/path/to/some/template.erb", :layout => true, :status => 404
# render :file => "c:/path/to/some/template.erb", :layout => true, :status => 404
#
# # Renders a template relative to the template root and chooses the proper file extension
# render :file => "some/template", :use_full_path => true
#
# === Rendering text
#
# Rendering of text is usually used for tests or for rendering prepared content, such as a cache. By default, text
@ -842,7 +855,7 @@ module ActionController #:nodoc:
raise DoubleRenderError, "Can only render or redirect once per action" if performed?
if options.nil?
return render_for_file(default_template_name, nil, true)
return render(:file => default_template_name, :layout => true)
elsif !extra_options.is_a?(Hash)
raise RenderError, "You called render with invalid options : #{options.inspect}, #{extra_options.inspect}"
else
@ -853,6 +866,9 @@ module ActionController #:nodoc:
end
end
response.layout = layout = pick_layout(options)
logger.info("Rendering template within #{layout}") if logger && layout
if content_type = options[:content_type]
response.content_type = content_type.to_s
end
@ -862,27 +878,21 @@ module ActionController #:nodoc:
end
if options.has_key?(:text)
render_for_text(options[:text], options[:status])
text = layout ? @template.render(options.merge(:text => options[:text], :layout => layout)) : options[:text]
render_for_text(text, options[:status])
else
if file = options[:file]
render_for_file(file, options[:status], options[:use_full_path], options[:locals] || {})
render_for_file(file, options[:status], layout, options[:locals] || {})
elsif template = options[:template]
render_for_file(template, options[:status], true, options[:locals] || {})
render_for_file(template, options[:status], layout, options[:locals] || {})
elsif inline = options[:inline]
add_variables_to_assigns
tmpl = ActionView::InlineTemplate.new(@template, options[:inline], options[:locals], options[:type])
render_for_text(@template.render_template(tmpl), options[:status])
render_for_text(@template.render(options.merge(:layout => layout)), options[:status])
elsif action_name = options[:action]
template = default_template_name(action_name.to_s)
if options[:layout] && !template_exempt_from_layout?(template)
render_with_a_layout(:file => template, :status => options[:status], :use_full_path => true, :layout => true)
else
render_with_no_layout(:file => template, :status => options[:status], :use_full_path => true)
end
render_for_file(default_template_name(action_name.to_s), options[:status], layout)
elsif xml = options[:xml]
response.content_type ||= Mime::XML
@ -894,36 +904,26 @@ module ActionController #:nodoc:
response.content_type ||= Mime::JSON
render_for_text(json, options[:status])
elsif partial = options[:partial]
partial = default_template_name if partial == true
add_variables_to_assigns
if collection = options[:collection]
render_for_text(
@template.send!(:render_partial_collection, partial, collection,
options[:spacer_template], options[:locals]), options[:status]
)
elsif options[:partial]
options[:partial] = default_template_name if options[:partial] == true
if layout
render_for_text(@template.render(:text => @template.render(options), :layout => layout), options[:status])
else
render_for_text(
@template.send!(:render_partial, partial,
ActionView::Base::ObjectWrapper.new(options[:object]), options[:locals]), options[:status]
)
render_for_text(@template.render(options), options[:status])
end
elsif options[:update]
add_variables_to_assigns
@template.send! :evaluate_assigns
@template.send(:_evaluate_assigns_and_ivars)
generator = ActionView::Helpers::PrototypeHelper::JavaScriptGenerator.new(@template, &block)
response.content_type = Mime::JS
render_for_text(generator.to_s, options[:status])
elsif options[:nothing]
# Safari doesn't pass the headers of the return if the response is zero length
render_for_text(" ", options[:status])
render_for_text(nil, options[:status])
else
render_for_file(default_template_name, options[:status], true)
render_for_file(default_template_name, options[:status], layout)
end
end
end
@ -934,7 +934,6 @@ module ActionController #:nodoc:
render(options, &block)
ensure
erase_render_results
forget_variables_added_to_assigns
reset_variables_added_to_assigns
end
@ -966,7 +965,6 @@ module ActionController #:nodoc:
render :nothing => true, :status => status
end
# Clears the rendered results, allowing for another render to be performed.
def erase_render_results #:nodoc:
response.body = nil
@ -1051,26 +1049,73 @@ module ActionController #:nodoc:
status = 302
end
response.redirected_to= options
logger.info("Redirected to #{options}") if logger && logger.info?
case options
when %r{^\w+://.*}
raise DoubleRenderError if performed?
logger.info("Redirected to #{options}") if logger && logger.info?
response.redirect(options, interpret_status(status))
response.redirected_to = options
@performed_redirect = true
redirect_to_full_url(options, status)
when String
redirect_to(request.protocol + request.host_with_port + options, :status=>status)
redirect_to_full_url(request.protocol + request.host_with_port + options, status)
when :back
request.env["HTTP_REFERER"] ? redirect_to(request.env["HTTP_REFERER"], :status=>status) : raise(RedirectBackError)
when Hash
redirect_to(url_for(options), :status=>status)
response.redirected_to = options
if referer = request.headers["Referer"]
redirect_to(referer, :status=>status)
else
raise RedirectBackError
end
else
redirect_to(url_for(options), :status=>status)
redirect_to_full_url(url_for(options), status)
end
end
def redirect_to_full_url(url, status)
raise DoubleRenderError if performed?
response.redirect(url, interpret_status(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
@ -1106,10 +1151,9 @@ module ActionController #:nodoc:
private
def render_for_file(template_path, status = nil, use_full_path = false, locals = {}) #:nodoc:
add_variables_to_assigns
def render_for_file(template_path, status = nil, layout = nil, locals = {}) #:nodoc:
logger.info("Rendering #{template_path}" + (status ? " (#{status})" : '')) if logger
render_for_text(@template.render_file(template_path, use_full_path, locals), status)
render_for_text @template.render(:file => template_path, :locals => locals, :layout => layout), status
end
def render_for_text(text = nil, status = nil, append_response = false) #:nodoc:
@ -1121,13 +1165,17 @@ module ActionController #:nodoc:
response.body ||= ''
response.body << text.to_s
else
response.body = text.is_a?(Proc) ? text : text.to_s
response.body = case text
when Proc then text
when nil then " " # Safari doesn't pass the headers of the return if the response is zero length
else text.to_s
end
end
end
def initialize_template_class(response)
response.template = ActionView::Base.new(self.class.view_paths, {}, self)
response.template.extend self.class.master_helper_module
response.template.helpers.send :include, self.class.master_helper_module
response.redirected_to = nil
@performed_render = @performed_redirect = false
end
@ -1140,7 +1188,6 @@ module ActionController #:nodoc:
@_session = @_response.session
@template = @_response.template
@assigns = @_response.template.assigns
@_headers = @_response.headers
end
@ -1162,16 +1209,16 @@ module ActionController #:nodoc:
end
def perform_action
if self.class.action_methods.include?(action_name)
if action_methods.include?(action_name)
send(action_name)
default_render unless performed?
elsif respond_to? :method_missing
method_missing action_name
default_render unless performed?
elsif template_exists? && template_public?
elsif template_exists?
default_render
else
raise UnknownAction, "No action responded to #{action_name}", caller
raise UnknownAction, "No action responded to #{action_name}. Actions: #{action_methods.sort.to_sentence}", caller
end
end
@ -1184,43 +1231,30 @@ module ActionController #:nodoc:
end
def assign_default_content_type_and_charset
response.content_type ||= Mime::HTML
response.charset ||= self.class.default_charset unless sending_file?
end
def sending_file?
response.headers["Content-Transfer-Encoding"] == "binary"
response.assign_default_content_type_and_charset!
end
deprecate :assign_default_content_type_and_charset => :'response.assign_default_content_type_and_charset!'
def action_methods
self.class.action_methods
end
def self.action_methods
@action_methods ||= Set.new(public_instance_methods.map(&:to_s)) - hidden_actions
end
def add_variables_to_assigns
unless @variables_added
add_instance_variables_to_assigns
@variables_added = true
end
end
def forget_variables_added_to_assigns
@variables_added = nil
@action_methods ||=
# All public instance methods of this class, including ancestors
public_instance_methods(true).map { |m| m.to_s }.to_set -
# Except for public instance methods of Base and its ancestors
Base.public_instance_methods(true).map { |m| m.to_s } +
# Be sure to include shadowed public instance methods of this class
public_instance_methods(false).map { |m| m.to_s } -
# And always exclude explicitly hidden actions
hidden_actions
end
def reset_variables_added_to_assigns
@template.instance_variable_set("@assigns_added", nil)
end
def add_instance_variables_to_assigns
(instance_variable_names - @@protected_view_variables).each do |var|
@assigns[var[1..-1]] = instance_variable_get(var)
end
end
def request_origin
# this *needs* to be cached!
# otherwise you'd get different results if calling it more than once
@ -1236,17 +1270,9 @@ module ActionController #:nodoc:
end
def template_exists?(template_name = default_template_name)
@template.finder.file_exists?(template_name)
end
def template_public?(template_name = default_template_name)
@template.file_public?(template_name)
end
def template_exempt_from_layout?(template_name = default_template_name)
extension = @template && @template.finder.pick_template_extension(template_name)
name_with_extension = !template_name.include?('.') && extension ? "#{template_name}.#{extension}" : template_name
@@exempt_from_layout.any? { |ext| name_with_extension =~ ext }
@template.send(:_pick_template, template_name) ? true : false
rescue ActionView::MissingTemplate
false
end
def default_template_name(action_name = self.action_name)
@ -1256,7 +1282,7 @@ module ActionController #:nodoc:
action_name = strip_out_controller(action_name)
end
end
"#{self.class.controller_path}/#{action_name}"
"#{self.controller_path}/#{action_name}"
end
def strip_out_controller(path)
@ -1264,7 +1290,7 @@ module ActionController #:nodoc:
end
def template_path_includes_controller?(path)
self.class.controller_path.split('/')[-1] == path.split('/')[0]
self.controller_path.split('/')[-1] == path.split('/')[0]
end
def process_cleanup