Rails 2.1

Update to Rails 2.1 final.
This commit is contained in:
Jacques Distler 2008-06-02 01:35:38 -05:00
parent fd554cce90
commit 516d6dfac0
257 changed files with 4058 additions and 1933 deletions

View file

@ -1,7 +1,8 @@
module ActionController
module Assertions
module ModelAssertions
# Ensures that the passed record is valid by ActiveRecord standards and returns any error messages if it is not.
# Ensures that the passed record is valid by Active Record standards and
# returns any error messages if it is not.
#
# ==== Examples
#

View file

@ -59,7 +59,7 @@ module ActionController
end
end
# Asserts that the provided options can be used to generate the provided path. This is the inverse of #assert_recognizes.
# Asserts that the provided options can be used to generate the provided path. This is the inverse of +assert_recognizes+.
# The +extras+ parameter is used to tell the request the names and values of additional request parameters that would be in
# a query string. The +message+ parameter allows you to specify a custom error message for assertion failures.
#
@ -96,8 +96,8 @@ module ActionController
end
# Asserts that path and options match both ways; in other words, it verifies that <tt>path</tt> generates
# <tt>options</tt> and then that <tt>options</tt> generates <tt>path</tt>. This essentially combines #assert_recognizes
# and #assert_generates into one step.
# <tt>options</tt> and then that <tt>options</tt> generates <tt>path</tt>. This essentially combines +assert_recognizes+
# and +assert_generates+ into one step.
#
# The +extras+ hash allows you to specify options that would normally be provided as a query string to the action. The
# +message+ parameter allows you to specify a custom error message to display upon failure.

View file

@ -12,12 +12,12 @@ module ActionController
NO_STRIP = %w{pre script style textarea}
end
# Adds the #assert_select method for use in Rails functional
# Adds the +assert_select+ method for use in Rails functional
# test cases, which can be used to make assertions on the response HTML of a controller
# action. You can also call #assert_select within another #assert_select to
# action. You can also call +assert_select+ within another +assert_select+ to
# make assertions on elements selected by the enclosing assertion.
#
# Use #css_select to select elements without making an assertions, either
# Use +css_select+ to select elements without making an assertions, either
# from the response HTML or elements selected by the enclosing assertion.
#
# In addition to HTML responses, you can make the following assertions:
@ -44,8 +44,8 @@ module ActionController
# base element and any of its children. Returns an empty array if no
# match is found.
#
# The selector may be a CSS selector expression (+String+), an expression
# with substitution values (+Array+) or an HTML::Selector object.
# The selector may be a CSS selector expression (String), an expression
# with substitution values (Array) or an HTML::Selector object.
#
# ==== Examples
# # Selects all div tags
@ -114,8 +114,8 @@ module ActionController
# starting from (and including) that element and all its children in
# depth-first order.
#
# If no element if specified, calling #assert_select will select from the
# response HTML. Calling #assert_select inside an #assert_select block will
# If no element if specified, calling +assert_select+ will select from the
# response HTML. Calling #assert_select inside an +assert_select+ block will
# run the assertion for each element selected by the enclosing assertion.
#
# ==== Example
@ -130,7 +130,7 @@ module ActionController
# assert_select "li"
# end
#
# The selector may be a CSS selector expression (+String+), an expression
# The selector may be a CSS selector expression (String), an expression
# with substitution values, or an HTML::Selector object.
#
# === Equality Tests
@ -356,16 +356,16 @@ module ActionController
#
# === Using blocks
#
# Without a block, #assert_select_rjs merely asserts that the response
# Without a block, +assert_select_rjs+ merely asserts that the response
# contains one or more RJS statements that replace or update content.
#
# With a block, #assert_select_rjs also selects all elements used in
# With a block, +assert_select_rjs+ also selects all elements used in
# these statements and passes them to the block. Nested assertions are
# supported.
#
# Calling #assert_select_rjs with no arguments and using nested asserts
# Calling +assert_select_rjs+ with no arguments and using nested asserts
# asserts that the HTML content is returned by one or more RJS statements.
# Using #assert_select directly makes the same assertion on the content,
# Using +assert_select+ directly makes the same assertion on the content,
# but without distinguishing whether the content is returned in an HTML
# or JavaScript.
#
@ -601,7 +601,7 @@ module ActionController
RJS_PATTERN_UNICODE_ESCAPED_CHAR = /\\u([0-9a-zA-Z]{4})/
end
# #assert_select and #css_select call this to obtain the content in the HTML
# +assert_select+ and +css_select+ call this to obtain the content in the HTML
# page, or from all the RJS statements, depending on the type of response.
def response_from_page_or_rjs()
content_type = @response.content_type

View file

@ -91,7 +91,7 @@ module ActionController
# :descendant => { :tag => "span",
# :child => /hello world/ }
#
# <b>Please note</b>: #assert_tag and #assert_no_tag only work
# <b>Please note</b>: +assert_tag+ and +assert_no_tag+ only work
# with well-formed XHTML. They recognize a few tags as implicitly self-closing
# (like br and hr and such) but will not work correctly with tags
# that allow optional closing tags (p, li, td). <em>You must explicitly
@ -104,8 +104,8 @@ module ActionController
end
end
# Identical to #assert_tag, but asserts that a matching tag does _not_
# exist. (See #assert_tag for a full discussion of the syntax.)
# Identical to +assert_tag+, but asserts that a matching tag does _not_
# exist. (See +assert_tag+ for a full discussion of the syntax.)
#
# === Examples
# # Assert that there is not a "div" containing a "p"

View file

@ -104,7 +104,7 @@ module ActionController #:nodoc:
# end
#
# Actions, by default, render a template in the <tt>app/views</tt> directory corresponding to the name of the controller and action
# after executing code in the action. For example, the +index+ action of the +GuestBookController+ would render the
# after executing code in the action. For example, the +index+ action of the GuestBookController would render the
# template <tt>app/views/guestbook/index.erb</tt> by default after populating the <tt>@entries</tt> instance variable.
#
# Unlike index, the sign action will not render a template. After performing its main purpose (creating a
@ -118,10 +118,10 @@ module ActionController #:nodoc:
#
# Requests are processed by the Action Controller framework by extracting the value of the "action" key in the request parameters.
# This value should hold the name of the action to be performed. Once the action has been identified, the remaining
# request parameters, the session (if one is available), and the full request with all the http headers are made available to
# request parameters, the session (if one is available), and the full request with all the HTTP headers are made available to
# the action through instance variables. Then the action is performed.
#
# The full request object is available with the request accessor and is primarily used to query for http headers. These queries
# The full request object is available with the request accessor and is primarily used to query for HTTP headers. These queries
# are made by accessing the environment hash, like this:
#
# def server_ip
@ -259,12 +259,12 @@ module ActionController #:nodoc:
DEFAULT_RENDER_STATUS_CODE = "200 OK"
include StatusCodes
# 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)
# 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:
# ActionController::Base.asset_host = "http://assets.example.com"
@ -291,10 +291,10 @@ module ActionController #:nodoc:
cattr_accessor :allow_concurrency
# Modern REST web services often need to submit complex data to the web application.
# The param_parsers hash lets you register handlers which will process the http body and add parameters to the
# <tt>params</tt> hash. These handlers are invoked for post and put requests.
# The <tt>@@param_parsers</tt> hash lets you register handlers which will process the HTTP body and add parameters to the
# <tt>params</tt> hash. These handlers are invoked for POST and PUT requests.
#
# By default application/xml is enabled. A XmlSimple class with the same param name as the root will be instantiated
# By default <tt>application/xml</tt> is enabled. A XmlSimple class with the same param name as the root will be instantiated
# in the <tt>params</tt>. This allows XML requests to mask themselves as regular form submissions, so you can have one
# action serve both regular forms and web service requests.
#
@ -307,7 +307,7 @@ module ActionController #:nodoc:
#
# Note: Up until release 1.1 of Rails, Action Controller would default to using XmlSimple configured to discard the
# root node for such requests. The new default is to keep the root, such that "<r><name>David</name></r>" results
# in params[:r][:name] for "David" instead of params[:name]. To get the old behavior, you can
# in <tt>params[:r][:name]</tt> for "David" instead of <tt>params[:name]</tt>. To get the old behavior, you can
# re-register XmlSimple as application/xml handler ike this:
#
# ActionController::Base.param_parsers[Mime::XML] =
@ -325,7 +325,7 @@ module ActionController #:nodoc:
# Controls the default charset for all renders.
@@default_charset = "utf-8"
cattr_accessor :default_charset
# The logger is used for generating information on the action run-time (including benchmarking) if available.
# Can be set to nil for no logging. Compatible with both Ruby's own Logger and Log4r loggers.
cattr_accessor :logger
@ -333,7 +333,7 @@ module ActionController #:nodoc:
# Controls the resource action separator
@@resource_action_separator = "/"
cattr_accessor :resource_action_separator
# Allow to override path names for default resources' actions
@@resources_path_names = { :new => 'new', :edit => 'edit' }
cattr_accessor :resources_path_names
@ -433,7 +433,7 @@ module ActionController #:nodoc:
end
# Adds a view_path to the front of the view_paths array.
# If the current class has no view paths, copy them from
# If the current class has no view paths, copy them from
# the superclass. This change will be visible for all future requests.
#
# ArticleController.prepend_view_path("views/default")
@ -444,9 +444,9 @@ module ActionController #:nodoc:
view_paths.unshift(*path)
ActionView::TemplateFinder.process_view_paths(path)
end
# Adds a view_path to the end of the view_paths array.
# If the current class has no view paths, copy them from
# If the current class has no view paths, copy them from
# the superclass. This change will be visible for all future requests.
#
# ArticleController.append_view_path("views/default")
@ -457,7 +457,7 @@ module ActionController #:nodoc:
view_paths.push(*path)
ActionView::TemplateFinder.process_view_paths(path)
end
# Replace sensitive parameter data from the request log.
# Filters parameters that have any of the arguments as a substring.
# Looks in all subhashes of the param hash for keys to filter.
@ -504,6 +504,7 @@ module ActionController #:nodoc:
filtered_parameters
end
protected :filter_parameters
end
# Don't render layouts for templates with the given extensions.
@ -643,12 +644,12 @@ module ActionController #:nodoc:
end
self.view_paths = []
# View load paths for controller.
def view_paths
@template.finder.view_paths
end
def view_paths=(value)
@template.finder.view_paths = value # Mutex needed
end
@ -662,7 +663,7 @@ module ActionController #:nodoc:
def prepend_view_path(path)
@template.finder.prepend_view_path(path) # Mutex needed
end
# Adds a view_path to the end of the view_paths array.
# This change affects the current request only.
#
@ -874,10 +875,10 @@ module ActionController #:nodoc:
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)
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
end
elsif xml = options[:xml]
response.content_type ||= Mime::XML
@ -895,12 +896,12 @@ module ActionController #:nodoc:
if collection = options[:collection]
render_for_text(
@template.send!(:render_partial_collection, partial, collection,
@template.send!(:render_partial_collection, partial, collection,
options[:spacer_template], options[:locals]), options[:status]
)
else
render_for_text(
@template.send!(:render_partial, partial,
@template.send!(:render_partial, partial,
ActionView::Base::ObjectWrapper.new(options[:object]), options[:locals]), options[:status]
)
end
@ -1024,7 +1025,7 @@ module ActionController #:nodoc:
# redirect_to articles_url
# redirect_to :back
#
# The redirection happens as a "302 Moved" header unless otherwise specified.
# The redirection happens as a "302 Moved" header unless otherwise specified.
#
# Examples:
# redirect_to post_url(@post), :status=>:found
@ -1035,17 +1036,17 @@ module ActionController #:nodoc:
# When using <tt>redirect_to :back</tt>, if there is no referrer,
# RedirectBackError will be raised. You may specify some fallback
# behavior for this case by rescuing RedirectBackError.
def redirect_to(options = {}, response_status = {}) #:doc:
def redirect_to(options = {}, response_status = {}) #:doc:
raise ActionControllerError.new("Cannot redirect to nil!") if options.nil?
if options.is_a?(Hash) && options[:status]
status = options.delete(:status)
elsif response_status[:status]
status = response_status[:status]
else
status = 302
if options.is_a?(Hash) && options[:status]
status = options.delete(:status)
elsif response_status[:status]
status = response_status[:status]
else
status = 302
end
case options
when %r{^\w+://.*}
raise DoubleRenderError if performed?
@ -1119,7 +1120,7 @@ module ActionController #:nodoc:
response.body = text.is_a?(Proc) ? text : text.to_s
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

View file

@ -9,7 +9,7 @@ module ActionController #:nodoc:
# class ListsController < ApplicationController
# before_filter :authenticate, :except => :public
# caches_page :public
# caches_action :show, :feed
# caches_action :index, :show, :feed
# end
#
# In this example, the public action doesn't require authentication, so it's possible to use the faster page caching method. But both the
@ -27,15 +27,19 @@ module ActionController #:nodoc:
# You can set modify the default action cache path by passing a :cache_path option. This will be passed directly to ActionCachePath.path_for. This is handy
# for actions with multiple possible routes that should be cached differently. If a block is given, it is called with the current controller instance.
#
# And you can also use :if to pass a Proc that specifies when the action should be cached.
#
# class ListsController < ApplicationController
# before_filter :authenticate, :except => :public
# caches_page :public
# caches_action :index, :if => Proc.new { |c| !c.request.format.json? } # cache if is not a JSON request
# caches_action :show, :cache_path => { :project => 1 }
# caches_action :show, :cache_path => Proc.new { |controller|
# controller.params[:user_id] ?
# caches_action :feed, :cache_path => Proc.new { |controller|
# controller.params[:user_id] ?
# controller.send(:user_list_url, c.params[:user_id], c.params[:id]) :
# controller.send(:list_url, c.params[:id]) }
# end
#
module Actions
def self.included(base) #:nodoc:
base.extend(ClassMethods)
@ -49,7 +53,8 @@ module ActionController #:nodoc:
# See ActionController::Caching::Actions for details.
def caches_action(*actions)
return unless cache_configured?
around_filter(ActionCacheFilter.new(*actions))
options = actions.extract_options!
around_filter(ActionCacheFilter.new(:cache_path => options.delete(:cache_path)), {:only => actions}.merge(options))
end
end
@ -67,16 +72,12 @@ module ActionController #:nodoc:
end
class ActionCacheFilter #:nodoc:
def initialize(*actions, &block)
@options = actions.extract_options!
@actions = Set.new(actions)
def initialize(options, &block)
@options = options
end
def before(controller)
return unless @actions.include?(controller.action_name.intern)
cache_path = ActionCachePath.new(controller, path_options_for(controller, @options))
if cache = controller.read_fragment(cache_path.path)
controller.rendered_action_cache = true
set_content_type!(controller, cache_path.extension)
@ -88,7 +89,7 @@ module ActionController #:nodoc:
end
def after(controller)
return if !@actions.include?(controller.action_name.intern) || controller.rendered_action_cache || !caching_allowed(controller)
return if controller.rendered_action_cache || !caching_allowed(controller)
controller.write_fragment(controller.action_cache_path.path, controller.response.body)
end
@ -105,16 +106,16 @@ module ActionController #:nodoc:
controller.request.get? && controller.response.headers['Status'].to_i == 200
end
end
class ActionCachePath
attr_reader :path, :extension
class << self
def path_for(controller, options)
new(controller, options).path
end
end
def initialize(controller, options = {})
@extension = extract_extension(controller.request.path)
path = controller.url_for(options).split('://').last
@ -122,16 +123,16 @@ module ActionController #:nodoc:
add_extension!(path, @extension)
@path = URI.unescape(path)
end
private
def normalize!(path)
path << 'index' if path[-1] == ?/
end
def add_extension!(path, extension)
path << ".#{extension}" if extension
end
def extract_extension(file_path)
# Don't want just what comes after the last '.' to accommodate multi part extensions
# such as tar.gz.
@ -140,4 +141,4 @@ module ActionController #:nodoc:
end
end
end
end
end

View file

@ -98,6 +98,17 @@ 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)
def fragment_exist?(key, options = nil)
return unless cache_configured?
key = fragment_cache_key(key)
self.class.benchmark "Cached fragment exists?: #{key}" do
cache_store.exist?(key, options)
end
end
# Name can take one of three forms:
# * String: This would normally take the form of a path like "pages/45/notes"
# * Hash: Is treated as an implicit call to url_for, like { :controller => "pages", :action => "notes", :id => 45 }
@ -124,4 +135,4 @@ module ActionController #:nodoc:
end
end
end
end
end

View file

@ -28,7 +28,7 @@ module ActionController #:nodoc:
# class ListsController < ApplicationController
# caches_action :index, :show, :public, :feed
# cache_sweeper OpenBar::Sweeper, :only => [ :edit, :destroy, :share ]
# end
# end
module Sweeping
def self.included(base) #:nodoc:
base.extend(ClassMethods)
@ -40,7 +40,7 @@ module ActionController #:nodoc:
sweepers.each do |sweeper|
ActiveRecord::Base.observers << sweeper if defined?(ActiveRecord) and defined?(ActiveRecord::Base)
sweeper_instance = (sweeper.is_a?(Symbol) ? Object.const_get(Inflector.classify(sweeper)) : sweeper).instance
sweeper_instance = (sweeper.is_a?(Symbol) ? Object.const_get(sweeper.to_s.classify) : sweeper).instance
if sweeper_instance.is_a?(Sweeper)
around_filter(sweeper_instance, :only => configuration[:only])
@ -94,4 +94,4 @@ module ActionController #:nodoc:
end
end
end
end
end

View file

@ -6,25 +6,24 @@ class CGI #:nodoc:
attr_accessor :name, :value, :path, :domain, :expires
attr_reader :secure, :http_only
# Create a new CGI::Cookie object.
# Creates a new CGI::Cookie object.
#
# The contents of the cookie can be specified as a +name+ and one
# or more +value+ arguments. Alternatively, the contents can
# be specified as a single hash argument. The possible keywords of
# this hash are as follows:
#
# name:: the name of the cookie. Required.
# value:: the cookie's value or list of values.
# path:: the path for which this cookie applies. Defaults to the
# base directory of the CGI script.
# domain:: the domain for which this cookie applies.
# expires:: the time at which this cookie expires, as a +Time+ object.
# secure:: whether this cookie is a secure cookie or not (default to
# false). Secure cookies are only transmitted to HTTPS
# servers.
# http_only:: whether this cookie can be accessed by client side scripts (e.g. document.cookie) or only over HTTP
# More details: http://msdn2.microsoft.com/en-us/library/system.web.httpcookie.httponly.aspx
# Defaults to false.
# * <tt>:name</tt> - The name of the cookie. Required.
# * <tt>:value</tt> - The cookie's value or list of values.
# * <tt>:path</tt> - The path for which this cookie applies. Defaults to the
# base directory of the CGI script.
# * <tt>:domain</tt> - The domain for which this cookie applies.
# * <tt>:expires</tt> - The time at which this cookie expires, as a Time object.
# * <tt>:secure</tt> - Whether this cookie is a secure cookie or not (defaults to
# +false+). Secure cookies are only transmitted to HTTPS servers.
# * <tt>:http_only</tt> - Whether this cookie can be accessed by client side scripts (e.g. document.cookie) or only over HTTP.
# More details in http://msdn2.microsoft.com/en-us/library/system.web.httpcookie.httponly.aspx. Defaults to +false+.
#
# These keywords correspond to attributes of the cookie object.
def initialize(name = '', *value)
if name.kind_of?(String)
@ -37,7 +36,7 @@ class CGI #:nodoc:
@path = nil
else
@name = name['name']
@value = Array(name['value'])
@value = (name['value'].kind_of?(String) ? [name['value']] : Array(name['value'])).delete_if(&:blank?)
@domain = name['domain']
@expires = name['expires']
@secure = name['secure'] || false
@ -56,17 +55,17 @@ class CGI #:nodoc:
super(@value)
end
# Set whether the Cookie is a secure cookie or not.
# Sets whether the Cookie is a secure cookie or not.
def secure=(val)
@secure = val == true
end
# Set whether the Cookie is an HTTP only cookie or not.
# Sets whether the Cookie is an HTTP only cookie or not.
def http_only=(val)
@http_only = val == true
end
# Convert the Cookie to its string representation.
# Converts the Cookie to its string representation.
def to_s
buf = ''
buf << @name << '='
@ -79,11 +78,17 @@ class CGI #:nodoc:
buf
end
# Parse a raw cookie string into a hash of cookie-name=>Cookie
# FIXME: work around broken 1.8.7 DelegateClass#respond_to?
def respond_to?(method, include_private = false)
return true if super(method)
return __getobj__.respond_to?(method, include_private)
end
# Parses a raw cookie string into a hash of <tt>cookie-name => cookie-object</tt>
# pairs.
#
# cookies = CGI::Cookie::parse("raw_cookie_string")
# # { "name1" => cookie1, "name2" => cookie2, ... }
# # => { "name1" => cookie1, "name2" => cookie2, ... }
#
def self.parse(raw_cookie)
cookies = Hash.new([])

View file

@ -16,6 +16,7 @@ module ActionController
def initialize_with_stdinput(type = nil, stdinput = $stdin)
@stdinput = stdinput
@stdinput.set_encoding(Encoding::BINARY) if @stdinput.respond_to?(:set_encoding)
initialize_without_stdinput(type || 'query')
end
end

View file

@ -15,7 +15,7 @@ module ActionController #:nodoc:
# * <tt>:new_session</tt> - if true, force creation of a new session. If not set, a new session is only created if none currently
# exists. If false, a new session is never created, and if none currently exists and the +session_id+ option is not set,
# an ArgumentError is raised.
# * <tt>:session_expires</tt> - the time the current session expires, as a +Time+ object. If not set, the session will continue
# * <tt>:session_expires</tt> - the time the current session expires, as a Time object. If not set, the session will continue
# indefinitely.
# * <tt>:session_domain</tt> - the hostname domain for which this session is valid. If not set, defaults to the hostname of the
# server.
@ -65,6 +65,7 @@ module ActionController #:nodoc:
# variable is already set, wrap it in a StringIO.
def body
if raw_post = env['RAW_POST_DATA']
raw_post.force_encoding(Encoding::BINARY) if raw_post.respond_to?(:force_encoding)
StringIO.new(raw_post)
else
@cgi.stdinput

View file

@ -100,10 +100,10 @@ module ActionController #:nodoc:
#
# Around filters wrap an action, executing code both before and after.
# They may be declared as method references, blocks, or objects responding
# to #filter or to both #before and #after.
# to +filter+ or to both +before+ and +after+.
#
# To use a method as an around_filter, pass a symbol naming the Ruby method.
# Yield (or block.call) within the method to run the action.
# To use a method as an +around_filter+, pass a symbol naming the Ruby method.
# Yield (or <tt>block.call</tt>) within the method to run the action.
#
# around_filter :catch_exceptions
#
@ -115,9 +115,9 @@ module ActionController #:nodoc:
# raise
# end
#
# To use a block as an around_filter, pass a block taking as args both
# To use a block as an +around_filter+, pass a block taking as args both
# the controller and the action block. You can't call yield directly from
# an around_filter block; explicitly call the action block instead:
# an +around_filter+ block; explicitly call the action block instead:
#
# around_filter do |controller, action|
# logger.debug "before #{controller.action_name}"
@ -125,7 +125,7 @@ module ActionController #:nodoc:
# logger.debug "after #{controller.action_name}"
# end
#
# To use a filter object with around_filter, pass an object responding
# To use a filter object with +around_filter+, pass an object responding
# to <tt>:filter</tt> or both <tt>:before</tt> and <tt>:after</tt>. With a
# filter method, yield to the block as above:
#
@ -137,7 +137,7 @@ module ActionController #:nodoc:
# end
# end
#
# With before and after methods:
# With +before+ and +after+ methods:
#
# around_filter Authorizer.new
#
@ -154,9 +154,9 @@ module ActionController #:nodoc:
# end
# end
#
# If the filter has before and after methods, the before method will be
# called before the action. If before renders or redirects, the filter chain is
# halted and after will not be run. See Filter Chain Halting below for
# If the filter has +before+ and +after+ methods, the +before+ method will be
# called before the action. If +before+ renders or redirects, the filter chain is
# halted and +after+ will not be run. See Filter Chain Halting below for
# an example.
#
# == Filter chain skipping
@ -215,7 +215,7 @@ module ActionController #:nodoc:
#
# <tt>before_filter</tt> and <tt>around_filter</tt> may halt the request
# before a controller action is run. This is useful, for example, to deny
# access to unauthenticated users or to redirect from http to https.
# access to unauthenticated users or to redirect from HTTP to HTTPS.
# Simply call render or redirect. After filters will not be executed if the filter
# chain is halted.
#
@ -241,10 +241,10 @@ module ActionController #:nodoc:
# . /
# #after (actual filter code is run, unless the around filter does not yield)
#
# If #around returns before yielding, #after will still not be run. The #before
# filter and controller action will not be run. If #before renders or redirects,
# the second half of #around and will still run but #after and the
# action will not. If #around fails to yield, #after will not be run.
# If +around+ returns before yielding, +after+ will still not be run. The +before+
# filter and controller action will not be run. If +before+ renders or redirects,
# the second half of +around+ and will still run but +after+ and the
# action will not. If +around+ fails to yield, +after+ will not be run.
class FilterChain < ActiveSupport::Callbacks::CallbackChain #:nodoc:
def append_filter_to_chain(filters, filter_type, &block)
@ -471,7 +471,7 @@ module ActionController #:nodoc:
# Shorthand for append_after_filter since it's the most common.
alias :after_filter :append_after_filter
# If you append_around_filter A.new, B.new, the filter chain looks like
# If you <tt>append_around_filter A.new, B.new</tt>, the filter chain looks like
#
# B#before
# A#before
@ -479,13 +479,13 @@ module ActionController #:nodoc:
# A#after
# B#after
#
# With around filters which yield to the action block, #before and #after
# With around filters which yield to the action block, +before+ and +after+
# are the code before and after the yield.
def append_around_filter(*filters, &block)
filter_chain.append_filter_to_chain(filters, :around, &block)
end
# If you prepend_around_filter A.new, B.new, the filter chain looks like:
# If you <tt>prepend_around_filter A.new, B.new</tt>, the filter chain looks like:
#
# A#before
# B#before
@ -493,13 +493,13 @@ module ActionController #:nodoc:
# B#after
# A#after
#
# With around filters which yield to the action block, #before and #after
# With around filters which yield to the action block, +before+ and +after+
# are the code before and after the yield.
def prepend_around_filter(*filters, &block)
filter_chain.prepend_filter_to_chain(filters, :around, &block)
end
# Shorthand for append_around_filter since it's the most common.
# Shorthand for +append_around_filter+ since it's the most common.
alias :around_filter :append_around_filter
# Removes the specified filters from the +before+ filter chain. Note that this only works for skipping method-reference

View file

@ -20,7 +20,7 @@ module ActionController #:nodoc:
end
# The Rails framework provides a large number of helpers for working with +assets+, +dates+, +forms+,
# +numbers+ and +ActiveRecord+ objects, to name a few. These helpers are available to all templates
# +numbers+ and Active Record objects, to name a few. These helpers are available to all templates
# by default.
#
# In addition to using the standard template helpers provided in the Rails framework, creating custom helpers to
@ -32,7 +32,7 @@ module ActionController #:nodoc:
# controller which inherits from it.
#
# ==== Examples
# The +to_s+ method from the +Time+ class can be wrapped in a helper method to display a custom message if
# The +to_s+ method from the Time class can be wrapped in a helper method to display a custom message if
# the Time object is blank:
#
# module FormattedTimeHelper
@ -41,7 +41,7 @@ module ActionController #:nodoc:
# end
# end
#
# +FormattedTimeHelper+ can now be included in a controller, using the +helper+ class method:
# FormattedTimeHelper can now be included in a controller, using the +helper+ class method:
#
# class EventsController < ActionController::Base
# helper FormattedTimeHelper
@ -74,22 +74,22 @@ module ActionController #:nodoc:
# The +helper+ class method can take a series of helper module names, a block, or both.
#
# * <tt>*args</tt>: One or more +Modules+, +Strings+ or +Symbols+, or the special symbol <tt>:all</tt>.
# * <tt>*args</tt>: One or more modules, strings or symbols, or the special symbol <tt>:all</tt>.
# * <tt>&block</tt>: A block defining helper methods.
#
# ==== Examples
# When the argument is a +String+ or +Symbol+, the method will provide the "_helper" suffix, require the file
# When the argument is a string or symbol, the method will provide the "_helper" suffix, require the file
# and include the module in the template class. The second form illustrates how to include custom helpers
# when working with namespaced controllers, or other cases where the file containing the helper definition is not
# in one of Rails' standard load paths:
# helper :foo # => requires 'foo_helper' and includes FooHelper
# helper 'resources/foo' # => requires 'resources/foo_helper' and includes Resources::FooHelper
#
# When the argument is a +Module+, it will be included directly in the template class.
# When the argument is a module it will be included directly in the template class.
# helper FooHelper # => includes FooHelper
#
# When the argument is the symbol <tt>:all</tt>, the controller will include all helpers from
# <tt>app/helpers/**/*.rb</tt> under +RAILS_ROOT+.
# <tt>app/helpers/**/*.rb</tt> under RAILS_ROOT.
# helper :all
#
# Additionally, the +helper+ class method can receive and evaluate a block, making the methods defined available

View file

@ -58,7 +58,7 @@ module ActionController
class MultiPartNeededException < Exception
end
# Create and initialize a new +Session+ instance.
# Create and initialize a new Session instance.
def initialize
reset!
end
@ -136,25 +136,25 @@ module ActionController
end
# Performs a GET request, following any subsequent redirect.
# See #request_via_redirect() for more information.
# See +request_via_redirect+ for more information.
def get_via_redirect(path, parameters = nil, headers = nil)
request_via_redirect(:get, path, parameters, headers)
end
# Performs a POST request, following any subsequent redirect.
# See #request_via_redirect() for more information.
# See +request_via_redirect+ for more information.
def post_via_redirect(path, parameters = nil, headers = nil)
request_via_redirect(:post, path, parameters, headers)
end
# Performs a PUT request, following any subsequent redirect.
# See #request_via_redirect() for more information.
# See +request_via_redirect+ for more information.
def put_via_redirect(path, parameters = nil, headers = nil)
request_via_redirect(:put, path, parameters, headers)
end
# Performs a DELETE request, following any subsequent redirect.
# See #request_via_redirect() for more information.
# See +request_via_redirect+ for more information.
def delete_via_redirect(path, parameters = nil, headers = nil)
request_via_redirect(:delete, path, parameters, headers)
end
@ -166,12 +166,12 @@ module ActionController
# Performs a GET request with the given parameters. The parameters may
# be +nil+, a Hash, or a string that is appropriately encoded
# (application/x-www-form-urlencoded or multipart/form-data). The headers
# should be a hash. The keys will automatically be upcased, with the
# (<tt>application/x-www-form-urlencoded</tt> or <tt>multipart/form-data</tt>).
# The headers should be a hash. The keys will automatically be upcased, with the
# prefix 'HTTP_' added if needed.
#
# You can also perform POST, PUT, DELETE, and HEAD requests with #post,
# #put, #delete, and #head.
# You can also perform POST, PUT, DELETE, and HEAD requests with +post+,
# +put+, +delete+, and +head+.
def get(path, parameters = nil, headers = nil)
process :get, path, parameters, headers
end
@ -228,6 +228,8 @@ module ActionController
super
stdinput.set_encoding(Encoding::BINARY) if stdinput.respond_to?(:set_encoding)
stdinput.force_encoding(Encoding::BINARY) if stdinput.respond_to?(:force_encoding)
@stdinput = stdinput.is_a?(IO) ? stdinput : StringIO.new(stdinput || '')
end
end
@ -382,6 +384,8 @@ module ActionController
multipart_requestify(params).map do |key, value|
if value.respond_to?(:original_filename)
File.open(value.path) do |f|
f.set_encoding(Encoding::BINARY) if f.respond_to?(:set_encoding)
<<-EOF
--#{boundary}\r
Content-Disposition: form-data; name="#{key}"; filename="#{CGI.escape(value.original_filename)}"\r

View file

@ -92,7 +92,7 @@ module ActionController #:nodoc:
# with the remaining data.
#
# Note that you can define your own XML parameter parser which would allow you to describe multiple entities
# in a single request (i.e., by wrapping them all in a single root note), but if you just go with the flow
# in a single request (i.e., by wrapping them all in a single root node), but if you just go with the flow
# and accept Rails' defaults, life will be much easier.
#
# If you need to use a MIME type which isn't supported by default, you can register your own handlers in

View file

@ -17,6 +17,10 @@ module Mime
# end
# end
class Type
@@html_types = Set.new [:html, :all]
@@unverifiable_types = Set.new [:text, :json, :csv, :xml, :rss, :atom, :yaml]
cattr_reader :html_types, :unverifiable_types
# A simple helper class used in parsing the accept header
class AcceptItem #:nodoc:
attr_accessor :order, :name, :q
@ -100,7 +104,7 @@ module Mime
list[text_xml].name = Mime::XML.to_s
end
# Look for more specific xml-based types and sort them ahead of app/xml
# Look for more specific XML-based types and sort them ahead of app/xml
if app_xml
idx = app_xml
@ -153,12 +157,21 @@ module Mime
synonym.to_s == mime_type.to_s || synonym.to_sym == mime_type.to_sym
end
end
# Returns true if Action Pack should check requests using this Mime Type for possible request forgery. See
# ActionController::RequestForgerProtection.
def verify_request?
!@@unverifiable_types.include?(to_sym)
end
def html?
@@html_types.include?(to_sym) || @string =~ /html/
end
private
def method_missing(method, *args)
if method.to_s =~ /(\w+)\?$/
mime_type = $1.downcase.to_sym
mime_type == @symbol || (mime_type == :html && @symbol == :all)
$1.downcase.to_sym == to_sym
else
super
end

View file

@ -17,4 +17,4 @@ Mime::Type.register "multipart/form-data", :multipart_form
Mime::Type.register "application/x-www-form-urlencoded", :url_encoded_form
# http://www.ietf.org/rfc/rfc4627.txt
Mime::Type.register "application/json", :json, %w( text/x-json )
Mime::Type.register "application/json", :json, %w( text/x-json )

View file

@ -1,6 +1,6 @@
module ActionController
# Polymorphic URL helpers are methods for smart resolution to a named route call when
# given an ActiveRecord model instance. They are to be used in combination with
# given an Active Record model instance. They are to be used in combination with
# ActionController::Resources.
#
# These methods are useful when you want to generate correct URL or path to a RESTful
@ -9,7 +9,9 @@ module ActionController
# Nested resources and/or namespaces are also supported, as illustrated in the example:
#
# polymorphic_url([:admin, @article, @comment])
# #-> results in:
#
# results in:
#
# admin_article_comment_url(@article, @comment)
#
# == Usage within the framework
@ -38,11 +40,8 @@ module ActionController
#
# Example usage:
#
# edit_polymorphic_path(@post)
# #=> /posts/1/edit
#
# formatted_polymorphic_path([@post, :pdf])
# #=> /posts/1.pdf
# edit_polymorphic_path(@post) # => "/posts/1/edit"
# formatted_polymorphic_path([@post, :pdf]) # => "/posts/1.pdf"
module PolymorphicRoutes
# Constructs a call to a named RESTful route for the given record and returns the
# resulting URL string. For example:

View file

@ -466,8 +466,8 @@ EOM
parser.result
end
def parse_multipart_form_parameters(body, boundary, content_length, env)
parse_request_parameters(read_multipart(body, boundary, content_length, env))
def parse_multipart_form_parameters(body, boundary, body_size, env)
parse_request_parameters(read_multipart(body, boundary, body_size, env))
end
def extract_multipart_boundary(content_type_with_parameters)
@ -519,7 +519,7 @@ EOM
EOL = "\015\012"
def read_multipart(body, boundary, content_length, env)
def read_multipart(body, boundary, body_size, env)
params = Hash.new([])
boundary = "--" + boundary
quoted_boundary = Regexp.quote(boundary)
@ -529,8 +529,14 @@ EOM
# start multipart/form-data
body.binmode if defined? body.binmode
case body
when File
body.set_encoding(Encoding::BINARY) if body.respond_to?(:set_encoding)
when StringIO
body.string.force_encoding(Encoding::BINARY) if body.string.respond_to?(:force_encoding)
end
boundary_size = boundary.size + EOL.size
content_length -= boundary_size
body_size -= boundary_size
status = body.read(boundary_size)
if nil == status
raise EOFError, "no content body"
@ -541,7 +547,7 @@ EOM
loop do
head = nil
content =
if 10240 < content_length
if 10240 < body_size
UploadedTempfile.new("CGI")
else
UploadedStringIO.new
@ -563,24 +569,24 @@ EOM
buf[0 ... (buf.size - (EOL + boundary + EOL).size)] = ""
end
c = if bufsize < content_length
c = if bufsize < body_size
body.read(bufsize)
else
body.read(content_length)
body.read(body_size)
end
if c.nil? || c.empty?
raise EOFError, "bad content body"
end
buf.concat(c)
content_length -= c.size
body_size -= c.size
end
buf = buf.sub(/\A((?:.|\n)*?)(?:[\r\n]{1,2})?#{quoted_boundary}([\r\n]{1,2}|--)/n) do
content.print $1
if "--" == $2
content_length = -1
body_size = -1
end
boundary_end = $2.dup
boundary_end = $2.dup
""
end
@ -607,7 +613,7 @@ EOM
else
params[name] = [content]
end
break if content_length == -1
break if body_size == -1
end
raise EOFError, "bad boundary end of body part" unless boundary_end=~/--/

View file

@ -99,7 +99,7 @@ module ActionController #:nodoc:
end
def verifiable_request_format?
request.format.html? || request.format.js?
request.content_type.nil? || request.content_type.verify_request?
end
# Sets the token value for the current session. Pass a <tt>:secret</tt> option

View file

@ -17,13 +17,13 @@ module ActionController
reset!
end
def benchmark(n)
def benchmark(n, profiling = false)
@quiet = true
print ' '
result = Benchmark.realtime do
n.times do |i|
run
run(profiling)
print_progress(i)
end
end
@ -43,8 +43,15 @@ module ActionController
script = File.read(script_path)
source = <<-end_source
def run
#{script}
def run(profiling = false)
if profiling
RubyProf.resume do
#{script}
end
else
#{script}
end
old_request_count = request_count
reset!
self.request_count = old_request_count
@ -91,21 +98,22 @@ module ActionController
def profile(sandbox)
load_ruby_prof
results = RubyProf.profile { benchmark(sandbox) }
benchmark(sandbox, true)
results = RubyProf.stop
show_profile_results results
results
end
def benchmark(sandbox)
def benchmark(sandbox, profiling = false)
sandbox.request_count = 0
elapsed = sandbox.benchmark(options[:n]).to_f
elapsed = sandbox.benchmark(options[:n], profiling).to_f
count = sandbox.request_count.to_i
puts '%.2f sec, %d requests, %d req/sec' % [elapsed, count, count / elapsed]
end
def warmup(sandbox)
Benchmark.realtime { sandbox.run }
Benchmark.realtime { sandbox.run(false) }
end
def default_options
@ -136,6 +144,7 @@ module ActionController
protected
def load_ruby_prof
begin
gem 'ruby-prof', '>= 0.6.1'
require 'ruby-prof'
if mode = options[:measure]
RubyProf.measure_mode = RubyProf.const_get(mode.upcase)

View file

@ -199,10 +199,8 @@ module ActionController #:nodoc:
private
def perform_action_with_rescue #:nodoc:
perform_action_without_rescue
rescue Exception => exception # errors from action performed
return if rescue_action_with_handler(exception)
rescue_action(exception)
rescue Exception => exception
rescue_action_with_handler(exception) || rescue_action(exception)
end
def rescues_path(template_name)

View file

@ -191,7 +191,7 @@ module ActionController
# end
# end
#
# Along with the routes themselves, #resources generates named routes for use in
# Along with the routes themselves, +resources+ generates named routes for use in
# controllers and views. <tt>map.resources :messages</tt> produces the following named routes and helpers:
#
# Named Route Helpers
@ -208,7 +208,7 @@ module ActionController
# edit_message edit_message_url(id), hash_for_edit_message_url(id),
# edit_message_path(id), hash_for_edit_message_path(id)
#
# You can use these helpers instead of #url_for or methods that take #url_for parameters. For example:
# You can use these helpers instead of +url_for+ or methods that take +url_for+ parameters. For example:
#
# redirect_to :controller => 'messages', :action => 'index'
# # and
@ -406,7 +406,7 @@ module ActionController
# end
# end
#
# Along with the routes themselves, #resource generates named routes for
# Along with the routes themselves, +resource+ generates named routes for
# use in controllers and views. <tt>map.resource :account</tt> produces
# these named routes and helpers:
#

View file

@ -23,9 +23,9 @@ module ActionController
# Accepts a "route path" (a string defining a route), and returns the array
# of segments that corresponds to it. Note that the segment array is only
# partially initialized--the defaults and requirements, for instance, need
# to be set separately, via the #assign_route_options method, and the
# #optional? method for each segment will not be reliable until after
# #assign_route_options is called, as well.
# to be set separately, via the +assign_route_options+ method, and the
# <tt>optional?</tt> method for each segment will not be reliable until after
# +assign_route_options+ is called, as well.
def segments_for_route_path(path)
rest, segments = path, []

View file

@ -248,7 +248,7 @@ module ActionController
end
def extract_value
"#{local_name} = hash[:#{key}] && hash[:#{key}].collect { |path_component| CGI.escape(path_component) }.to_param #{"|| #{default.inspect}" if default}"
"#{local_name} = hash[:#{key}] && hash[:#{key}].collect { |path_component| CGI.escape(path_component.to_param, ActionController::Routing::Segment::UNSAFE_PCHAR) }.to_param #{"|| #{default.inspect}" if default}"
end
def default

View file

@ -34,7 +34,7 @@ require 'openssl' # to generate the HMAC message digest
# such as 'MD5', 'RIPEMD160', 'SHA256', etc.
#
# To generate a secret key for an existing application, run
# `rake secret` and set the key in config/environment.rb.
# "rake secret" and set the key in config/environment.rb.
#
# Note that changing digest or secret invalidates all existing sessions!
class CGI::Session::CookieStore
@ -130,17 +130,20 @@ class CGI::Session::CookieStore
# Marshal a session hash into safe cookie data. Include an integrity hash.
def marshal(session)
data = ActiveSupport::Base64.encode64(Marshal.dump(session)).chop
CGI.escape "#{data}--#{generate_digest(data)}"
"#{data}--#{generate_digest(data)}"
end
# Unmarshal cookie data to a hash and verify its integrity.
def unmarshal(cookie)
if cookie
data, digest = CGI.unescape(cookie).split('--')
unless digest == generate_digest(data)
data, digest = cookie.split('--')
# Do two checks to transparently support old double-escaped data.
unless digest == generate_digest(data) || digest == generate_digest(data = CGI.unescape(data))
delete
raise TamperedWithCookie
end
Marshal.load(ActiveSupport::Base64.decode64(data))
end
end

View file

@ -80,4 +80,4 @@ module ActionController
@request.remote_addr = '208.77.188.166' # example.com
end
end
end
end

View file

@ -3,7 +3,7 @@ require 'action_controller/test_case'
module ActionController #:nodoc:
class Base
# Process a test request called with a +TestRequest+ object.
# Process a test request called with a TestRequest object.
def self.process_test(request)
new.process_test(request)
end
@ -49,7 +49,7 @@ module ActionController #:nodoc:
# Either the RAW_POST_DATA environment variable or the URL-encoded request
# parameters.
def raw_post
env['RAW_POST_DATA'] ||= url_encoded_request_parameters
env['RAW_POST_DATA'] ||= returning(url_encoded_request_parameters) { |b| b.force_encoding(Encoding::BINARY) if b.respond_to?(:force_encoding) }
end
def port=(number)
@ -340,6 +340,7 @@ module ActionController #:nodoc:
@content_type = content_type
@original_filename = path.sub(/^.*#{File::SEPARATOR}([^#{File::SEPARATOR}]+)$/) { $1 }
@tempfile = Tempfile.new(@original_filename)
@tempfile.set_encoding(Encoding::BINARY) if @tempfile.respond_to?(:set_encoding)
@tempfile.binmode if binary
FileUtils.copy_file(path, @tempfile.path)
end
@ -357,7 +358,7 @@ module ActionController #:nodoc:
module TestProcess
def self.included(base)
# execute the request simulating a specific http method and set/volley the response
# execute the request simulating a specific HTTP method and set/volley the response
%w( get post put delete head ).each do |method|
base.class_eval <<-EOV, __FILE__, __LINE__
def #{method}(action, parameters = nil, session = nil, flash = nil)