aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoshua Peek <josh@joshpeek.com>2009-01-27 18:17:39 -0600
committerJoshua Peek <josh@joshpeek.com>2009-01-27 18:17:39 -0600
commita0f2b1d95d3785de92ae271fd7ea23e91c0cadc6 (patch)
treee125027e317889e6402dac147e03fc112c129aec
parenteb9af20b7cc0e374277cf330bdd404f9daab28ec (diff)
downloadrails-a0f2b1d95d3785de92ae271fd7ea23e91c0cadc6.tar.gz
rails-a0f2b1d95d3785de92ae271fd7ea23e91c0cadc6.tar.bz2
rails-a0f2b1d95d3785de92ae271fd7ea23e91c0cadc6.zip
Reorganize ActionController folder structure
-rw-r--r--.gitignore1
-rw-r--r--actionpack/lib/action_controller.rb94
-rw-r--r--actionpack/lib/action_controller/base/base.rb (renamed from actionpack/lib/action_controller/base.rb)502
-rw-r--r--actionpack/lib/action_controller/base/chained/benchmarking.rb (renamed from actionpack/lib/action_controller/benchmarking.rb)2
-rw-r--r--actionpack/lib/action_controller/base/chained/filters.rb (renamed from actionpack/lib/action_controller/filters.rb)0
-rw-r--r--actionpack/lib/action_controller/base/chained/flash.rb (renamed from actionpack/lib/action_controller/flash.rb)0
-rw-r--r--actionpack/lib/action_controller/base/cookies.rb (renamed from actionpack/lib/action_controller/cookies.rb)0
-rw-r--r--actionpack/lib/action_controller/base/headers.rb (renamed from actionpack/lib/action_controller/headers.rb)0
-rw-r--r--actionpack/lib/action_controller/base/helpers.rb (renamed from actionpack/lib/action_controller/helpers.rb)0
-rw-r--r--actionpack/lib/action_controller/base/http_authentication.rb (renamed from actionpack/lib/action_controller/http_authentication.rb)0
-rw-r--r--actionpack/lib/action_controller/base/layout.rb (renamed from actionpack/lib/action_controller/layout.rb)0
-rw-r--r--actionpack/lib/action_controller/base/redirect.rb91
-rw-r--r--actionpack/lib/action_controller/base/render.rb378
-rw-r--r--actionpack/lib/action_controller/base/request_forgery_protection.rb (renamed from actionpack/lib/action_controller/request_forgery_protection.rb)0
-rw-r--r--actionpack/lib/action_controller/base/responder.rb41
-rw-r--r--actionpack/lib/action_controller/base/streaming.rb (renamed from actionpack/lib/action_controller/streaming.rb)0
-rw-r--r--actionpack/lib/action_controller/base/verification.rb (renamed from actionpack/lib/action_controller/verification.rb)0
-rw-r--r--actionpack/lib/action_controller/cgi/ext.rb (renamed from actionpack/lib/action_controller/cgi_ext.rb)6
-rw-r--r--actionpack/lib/action_controller/cgi/ext/cookie.rb (renamed from actionpack/lib/action_controller/cgi_ext/cookie.rb)0
-rw-r--r--actionpack/lib/action_controller/cgi/ext/query_extension.rb (renamed from actionpack/lib/action_controller/cgi_ext/query_extension.rb)0
-rw-r--r--actionpack/lib/action_controller/cgi/ext/stdinput.rb (renamed from actionpack/lib/action_controller/cgi_ext/stdinput.rb)0
-rw-r--r--actionpack/lib/action_controller/cgi/process.rb (renamed from actionpack/lib/action_controller/cgi_process.rb)2
-rw-r--r--actionpack/lib/action_controller/dispatch/dispatcher.rb (renamed from actionpack/lib/action_controller/dispatcher.rb)2
-rw-r--r--actionpack/lib/action_controller/dispatch/params_parser.rb (renamed from actionpack/lib/action_controller/params_parser.rb)0
-rw-r--r--actionpack/lib/action_controller/dispatch/rack/failsafe.rb (renamed from actionpack/lib/action_controller/failsafe.rb)0
-rw-r--r--actionpack/lib/action_controller/dispatch/rack/lock.rb16
-rw-r--r--actionpack/lib/action_controller/dispatch/rack/middleware_stack.rb (renamed from actionpack/lib/action_controller/middleware_stack.rb)0
-rw-r--r--actionpack/lib/action_controller/dispatch/rack/middlewares.rb (renamed from actionpack/lib/action_controller/middlewares.rb)0
-rwxr-xr-xactionpack/lib/action_controller/dispatch/request.rb (renamed from actionpack/lib/action_controller/request.rb)0
-rw-r--r--actionpack/lib/action_controller/dispatch/request_parser.rb315
-rw-r--r--actionpack/lib/action_controller/dispatch/rescue.rb (renamed from actionpack/lib/action_controller/rescue.rb)4
-rw-r--r--actionpack/lib/action_controller/dispatch/response.rb (renamed from actionpack/lib/action_controller/response.rb)0
-rw-r--r--actionpack/lib/action_controller/dispatch/rewindable_input.rb (renamed from actionpack/lib/action_controller/rewindable_input.rb)0
-rw-r--r--actionpack/lib/action_controller/dispatch/status_codes.rb (renamed from actionpack/lib/action_controller/status_codes.rb)0
-rw-r--r--actionpack/lib/action_controller/dispatch/templates/rescues/_request_and_response.erb (renamed from actionpack/lib/action_controller/templates/rescues/_request_and_response.erb)0
-rw-r--r--actionpack/lib/action_controller/dispatch/templates/rescues/_trace.erb (renamed from actionpack/lib/action_controller/templates/rescues/_trace.erb)0
-rw-r--r--actionpack/lib/action_controller/dispatch/templates/rescues/diagnostics.erb (renamed from actionpack/lib/action_controller/templates/rescues/diagnostics.erb)0
-rw-r--r--actionpack/lib/action_controller/dispatch/templates/rescues/layout.erb (renamed from actionpack/lib/action_controller/templates/rescues/layout.erb)0
-rw-r--r--actionpack/lib/action_controller/dispatch/templates/rescues/missing_template.erb (renamed from actionpack/lib/action_controller/templates/rescues/missing_template.erb)0
-rw-r--r--actionpack/lib/action_controller/dispatch/templates/rescues/routing_error.erb (renamed from actionpack/lib/action_controller/templates/rescues/routing_error.erb)0
-rw-r--r--actionpack/lib/action_controller/dispatch/templates/rescues/template_error.erb (renamed from actionpack/lib/action_controller/templates/rescues/template_error.erb)0
-rw-r--r--actionpack/lib/action_controller/dispatch/templates/rescues/unknown_action.erb (renamed from actionpack/lib/action_controller/templates/rescues/unknown_action.erb)0
-rw-r--r--actionpack/lib/action_controller/dispatch/uploaded_file.rb (renamed from actionpack/lib/action_controller/uploaded_file.rb)0
-rw-r--r--actionpack/lib/action_controller/dispatch/url_encoded_pair_parser.rb (renamed from actionpack/lib/action_controller/url_encoded_pair_parser.rb)0
-rw-r--r--actionpack/lib/action_controller/mime/default_types.rb (renamed from actionpack/lib/action_controller/mime_types.rb)0
-rw-r--r--actionpack/lib/action_controller/mime/responds.rb (renamed from actionpack/lib/action_controller/mime_responds.rb)0
-rw-r--r--actionpack/lib/action_controller/mime/type.rb (renamed from actionpack/lib/action_controller/mime_type.rb)2
-rw-r--r--actionpack/lib/action_controller/record_identifier.rb2
-rw-r--r--actionpack/lib/action_controller/routing/generation/polymorphic_routes.rb (renamed from actionpack/lib/action_controller/polymorphic_routes.rb)0
-rw-r--r--actionpack/lib/action_controller/routing/generation/url_rewriter.rb (renamed from actionpack/lib/action_controller/url_rewriter.rb)0
-rw-r--r--actionpack/lib/action_controller/routing/resources.rb (renamed from actionpack/lib/action_controller/resources.rb)0
-rw-r--r--actionpack/lib/action_controller/session/management.rb (renamed from actionpack/lib/action_controller/session_management.rb)0
-rw-r--r--actionpack/lib/action_controller/testing/assertions/dom.rb (renamed from actionpack/lib/action_controller/assertions/dom_assertions.rb)0
-rw-r--r--actionpack/lib/action_controller/testing/assertions/model.rb (renamed from actionpack/lib/action_controller/assertions/model_assertions.rb)0
-rw-r--r--actionpack/lib/action_controller/testing/assertions/response.rb (renamed from actionpack/lib/action_controller/assertions/response_assertions.rb)0
-rw-r--r--actionpack/lib/action_controller/testing/assertions/routing.rb (renamed from actionpack/lib/action_controller/assertions/routing_assertions.rb)0
-rw-r--r--actionpack/lib/action_controller/testing/assertions/selector.rb (renamed from actionpack/lib/action_controller/assertions/selector_assertions.rb)0
-rw-r--r--actionpack/lib/action_controller/testing/assertions/tag.rb (renamed from actionpack/lib/action_controller/assertions/tag_assertions.rb)0
-rw-r--r--actionpack/lib/action_controller/testing/integration.rb (renamed from actionpack/lib/action_controller/integration.rb)0
-rw-r--r--actionpack/lib/action_controller/testing/performance.rb (renamed from actionpack/lib/action_controller/performance_test.rb)0
-rw-r--r--actionpack/lib/action_controller/testing/process.rb (renamed from actionpack/lib/action_controller/test_process.rb)0
-rw-r--r--actionpack/lib/action_controller/testing/test_case.rb (renamed from actionpack/lib/action_controller/test_case.rb)2
-rw-r--r--actionpack/lib/action_view/render/partials.rb28
-rw-r--r--actionpack/test/abstract_unit.rb3
-rw-r--r--actionpack/test/controller/send_file_test.rb2
-rw-r--r--actionpack/test/controller/test_test.rb2
-rw-r--r--activesupport/lib/active_support/memoizable.rb38
-rw-r--r--railties/lib/dispatcher.rb2
68 files changed, 976 insertions, 559 deletions
diff --git a/.gitignore b/.gitignore
index 28ee9cf2a8..bb1ca166e6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,6 +14,7 @@ railties/pkg
railties/test/500.html
railties/doc/guides/html/images
railties/doc/guides/html/stylesheets
+benches
*.rbc
*.swp
*.swo
diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb
index 6000ee15c6..d973cbb382 100644
--- a/actionpack/lib/action_controller.rb
+++ b/actionpack/lib/action_controller.rb
@@ -44,57 +44,61 @@ module ActionController
[Base, CGIHandler, CgiRequest, Request, Response, Http::Headers, UrlRewriter, UrlWriter]
end
- autoload :AbstractRequest, 'action_controller/request'
- autoload :Base, 'action_controller/base'
- autoload :Benchmarking, 'action_controller/benchmarking'
+ autoload :Base, 'action_controller/base/base'
+ autoload :Benchmarking, 'action_controller/base/chained/benchmarking'
autoload :Caching, 'action_controller/caching'
- autoload :Cookies, 'action_controller/cookies'
- autoload :Dispatcher, 'action_controller/dispatcher'
- autoload :Failsafe, 'action_controller/failsafe'
- autoload :Filters, 'action_controller/filters'
- autoload :Flash, 'action_controller/flash'
- autoload :Helpers, 'action_controller/helpers'
- autoload :HttpAuthentication, 'action_controller/http_authentication'
- autoload :Integration, 'action_controller/integration'
- autoload :IntegrationTest, 'action_controller/integration'
- autoload :Layout, 'action_controller/layout'
- autoload :MiddlewareStack, 'action_controller/middleware_stack'
- autoload :MimeResponds, 'action_controller/mime_responds'
- autoload :ParamsParser, 'action_controller/params_parser'
- autoload :PolymorphicRoutes, 'action_controller/polymorphic_routes'
+ autoload :Cookies, 'action_controller/base/cookies'
+ autoload :Dispatcher, 'action_controller/dispatch/dispatcher'
+ autoload :Failsafe, 'action_controller/dispatch/rack/failsafe'
+ autoload :Filters, 'action_controller/base/chained/filters'
+ autoload :Flash, 'action_controller/base/chained/flash'
+ autoload :Helpers, 'action_controller/base/helpers'
+ autoload :HttpAuthentication, 'action_controller/base/http_authentication'
+ autoload :Integration, 'action_controller/testing/integration'
+ autoload :IntegrationTest, 'action_controller/testing/integration'
+ autoload :Layout, 'action_controller/base/layout'
+ autoload :Lock, 'action_controller/dispatch/rack/lock'
+ autoload :MiddlewareStack, 'action_controller/dispatch/rack/middleware_stack'
+ autoload :MimeResponds, 'action_controller/mime/responds'
+ autoload :ParamsParser, 'action_controller/dispatch/params_parser'
+ autoload :PolymorphicRoutes, 'action_controller/routing/generation/polymorphic_routes'
autoload :RecordIdentifier, 'action_controller/record_identifier'
- autoload :Request, 'action_controller/request'
- autoload :RequestForgeryProtection, 'action_controller/request_forgery_protection'
- autoload :Rescue, 'action_controller/rescue'
- autoload :Resources, 'action_controller/resources'
- autoload :Response, 'action_controller/response'
- autoload :RewindableInput, 'action_controller/rewindable_input'
+ autoload :Redirector, 'action_controller/base/redirect'
+ autoload :Renderer, 'action_controller/base/render'
+ autoload :Request, 'action_controller/dispatch/request'
+ autoload :RequestForgeryProtection, 'action_controller/base/request_forgery_protection'
+ autoload :RequestParser, 'action_controller/dispatch/request_parser'
+ autoload :Rescue, 'action_controller/dispatch/rescue'
+ autoload :Resources, 'action_controller/routing/resources'
+ autoload :Responder, 'action_controller/base/responder'
+ autoload :Response, 'action_controller/dispatch/response'
+ autoload :RewindableInput, 'action_controller/dispatch/rewindable_input'
autoload :Routing, 'action_controller/routing'
- autoload :SessionManagement, 'action_controller/session_management'
- autoload :StatusCodes, 'action_controller/status_codes'
- autoload :Streaming, 'action_controller/streaming'
- autoload :TestCase, 'action_controller/test_case'
- autoload :TestProcess, 'action_controller/test_process'
+ autoload :SessionManagement, 'action_controller/session/management'
+ autoload :StatusCodes, 'action_controller/dispatch/status_codes'
+ autoload :Streaming, 'action_controller/base/streaming'
+ autoload :TestCase, 'action_controller/testing/test_case'
+ autoload :TestProcess, 'action_controller/testing/process'
autoload :Translation, 'action_controller/translation'
- autoload :UploadedFile, 'action_controller/uploaded_file'
- autoload :UploadedStringIO, 'action_controller/uploaded_file'
- autoload :UploadedTempfile, 'action_controller/uploaded_file'
- autoload :UrlEncodedPairParser, 'action_controller/url_encoded_pair_parser'
- autoload :UrlRewriter, 'action_controller/url_rewriter'
- autoload :UrlWriter, 'action_controller/url_rewriter'
- autoload :Verification, 'action_controller/verification'
+ autoload :UploadedFile, 'action_controller/dispatch/uploaded_file'
+ autoload :UploadedStringIO, 'action_controller/dispatch/uploaded_file'
+ autoload :UploadedTempfile, 'action_controller/dispatch/uploaded_file'
+ autoload :UrlEncodedPairParser, 'action_controller/dispatch/url_encoded_pair_parser'
+ autoload :UrlRewriter, 'action_controller/routing/generation/url_rewriter'
+ autoload :UrlWriter, 'action_controller/routing/generation/url_rewriter'
+ autoload :Verification, 'action_controller/base/verification'
module Assertions
- autoload :DomAssertions, 'action_controller/assertions/dom_assertions'
- autoload :ModelAssertions, 'action_controller/assertions/model_assertions'
- autoload :ResponseAssertions, 'action_controller/assertions/response_assertions'
- autoload :RoutingAssertions, 'action_controller/assertions/routing_assertions'
- autoload :SelectorAssertions, 'action_controller/assertions/selector_assertions'
- autoload :TagAssertions, 'action_controller/assertions/tag_assertions'
+ autoload :DomAssertions, 'action_controller/testing/assertions/dom'
+ autoload :ModelAssertions, 'action_controller/testing/assertions/model'
+ autoload :ResponseAssertions, 'action_controller/testing/assertions/response'
+ autoload :RoutingAssertions, 'action_controller/testing/assertions/routing'
+ autoload :SelectorAssertions, 'action_controller/testing/assertions/selector'
+ autoload :TagAssertions, 'action_controller/testing/assertions/tag'
end
module Http
- autoload :Headers, 'action_controller/headers'
+ autoload :Headers, 'action_controller/base/headers'
end
module Session
@@ -102,13 +106,9 @@ module ActionController
autoload :CookieStore, 'action_controller/session/cookie_store'
autoload :MemCacheStore, 'action_controller/session/mem_cache_store'
end
-
- # DEPRECATE: Remove CGI support
- autoload :CgiRequest, 'action_controller/cgi_process'
- autoload :CGIHandler, 'action_controller/cgi_process'
end
-autoload :Mime, 'action_controller/mime_type'
+autoload :Mime, 'action_controller/mime/type'
autoload :HTML, 'action_controller/vendor/html-scanner'
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base/base.rb
index 78c8bf0647..84371643d7 100644
--- a/actionpack/lib/action_controller/base.rb
+++ b/actionpack/lib/action_controller/base/base.rb
@@ -58,22 +58,6 @@ module ActionController #:nodoc:
end
end
- class DoubleRenderError < ActionControllerError #:nodoc:
- DEFAULT_MESSAGE = "Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like \"redirect_to(...) and return\"."
-
- def initialize(message = nil)
- super(message || DEFAULT_MESSAGE)
- end
- end
-
- class RedirectBackError < ActionControllerError #:nodoc:
- DEFAULT_MESSAGE = 'No HTTP_REFERER was set in the request to this action, so redirect_to :back could not be called successfully. If this is a test, make sure to specify request.env["HTTP_REFERER"].'
-
- def initialize(message = nil)
- super(message || DEFAULT_MESSAGE)
- end
- end
-
class UnknownHttpMethod < ActionControllerError #:nodoc:
end
@@ -247,7 +231,6 @@ module ActionController #:nodoc:
# end
#
class Base
- DEFAULT_RENDER_STATUS_CODE = "200 OK"
include StatusCodes
@@ -301,7 +284,10 @@ module ActionController #:nodoc:
# A YAML parser is also available and can be turned on with:
#
# ActionController::Base.param_parsers[Mime::YAML] = :yaml
- @@param_parsers = {}
+ @@param_parsers = { Mime::MULTIPART_FORM => :multipart_form,
+ Mime::URL_ENCODED_FORM => :url_encoded_form,
+ Mime::XML => :xml_simple,
+ Mime::JSON => :json }
cattr_accessor :param_parsers
# Controls the default charset for all renders.
@@ -644,7 +630,7 @@ module ActionController #:nodoc:
end
def session_enabled?
- ActiveSupport::Deprecation.warn("Sessions are now lazy loaded. So if you don't access them, consider them disabled.", caller)
+ request.session_options && request.session_options[:disabled] != false
end
self.view_paths = []
@@ -678,331 +664,6 @@ module ActionController #:nodoc:
@template.view_paths.push(*path)
end
- protected
- # Renders the content that will be returned to the browser as the response body.
- #
- # === Rendering an action
- #
- # Action rendering is the most common form and the type used automatically by Action Controller when nothing else is
- # specified. By default, actions are rendered within the current layout (if one exists).
- #
- # # Renders the template for the action "goal" within the current controller
- # render :action => "goal"
- #
- # # Renders the template for the action "short_goal" within the current controller,
- # # but without the current active layout
- # render :action => "short_goal", :layout => false
- #
- # # Renders the template for the action "long_goal" within the current controller,
- # # but with a custom layout
- # render :action => "long_goal", :layout => "spectacular"
- #
- # === Rendering partials
- #
- # Partial rendering in a controller is most commonly used together with Ajax calls that only update one or a few elements on a page
- # without reloading. Rendering of partials from the controller makes it possible to use the same partial template in
- # both the full-page rendering (by calling it from within the template) and when sub-page updates happen (from the
- # controller action responding to Ajax calls). By default, the current layout is not used.
- #
- # # Renders the same partial with a local variable.
- # render :partial => "person", :locals => { :name => "david" }
- #
- # # Renders the partial, making @new_person available through
- # # the local variable 'person'
- # render :partial => "person", :object => @new_person
- #
- # # Renders a collection of the same partial by making each element
- # # of @winners available through the local variable "person" as it
- # # 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"
- #
- # # Renders a collection of partials located in a view subfolder
- # # outside of our current controller. In this example we will be
- # # rendering app/views/shared/_note.r(html|xml) Inside the partial
- # # each element of @new_notes is available as the local var "note".
- # render :partial => "shared/note", :collection => @new_notes
- #
- # # Renders the partial with a status code of 500 (internal error).
- # render :partial => "broken", :status => 500
- #
- # Note that the partial filename must also be a valid Ruby variable name,
- # so e.g. 2005 and register-user are invalid.
- #
- #
- # == Automatic etagging
- #
- # Rendering will automatically insert the etag header on 200 OK responses. The etag is calculated using MD5 of the
- # response body. If a request comes in that has a matching etag, the response will be changed to a 304 Not Modified
- # and the response body will be set to an empty string. No etag header will be inserted if it's already set.
- #
- # === Rendering a template
- #
- # Template rendering works just like action rendering except that it takes a path relative to the template root.
- # The current layout is automatically applied.
- #
- # # Renders the template located in [TEMPLATE_ROOT]/weblog/show.r(html|xml) (in Rails, app/views/weblog/show.erb)
- # render :template => "weblog/show"
- #
- # # Renders the template with a local variable
- # render :template => "weblog/show", :locals => {:customer => Customer.new}
- #
- # === Rendering a file
- #
- # File rendering works just like action rendering except that it takes a filesystem path. By default, the path
- # is assumed to be absolute, and the current layout is not applied.
- #
- # # Renders the template located at the absolute filesystem path
- # render :file => "/path/to/some/template.erb"
- # render :file => "c:/path/to/some/template.erb"
- #
- # # Renders a template within the current layout, and with a 404 status code
- # render :file => "/path/to/some/template.erb", :layout => true, :status => 404
- # render :file => "c:/path/to/some/template.erb", :layout => true, :status => 404
- #
- # === Rendering text
- #
- # Rendering of text is usually used for tests or for rendering prepared content, such as a cache. By default, text
- # rendering is not done within the active layout.
- #
- # # Renders the clear text "hello world" with status code 200
- # render :text => "hello world!"
- #
- # # Renders the clear text "Explosion!" with status code 500
- # render :text => "Explosion!", :status => 500
- #
- # # Renders the clear text "Hi there!" within the current active layout (if one exists)
- # render :text => "Hi there!", :layout => true
- #
- # # Renders the clear text "Hi there!" within the layout
- # # placed in "app/views/layouts/special.r(html|xml)"
- # render :text => "Hi there!", :layout => "special"
- #
- # The <tt>:text</tt> option can also accept a Proc object, which can be used to manually control the page generation. This should
- # generally be avoided, as it violates the separation between code and content, and because almost everything that can be
- # done with this method can also be done more cleanly using one of the other rendering methods, most notably templates.
- #
- # # Renders "Hello from code!"
- # render :text => proc { |response, output| output.write("Hello from code!") }
- #
- # === Rendering XML
- #
- # Rendering XML sets the content type to application/xml.
- #
- # # Renders '<name>David</name>'
- # render :xml => {:name => "David"}.to_xml
- #
- # It's not necessary to call <tt>to_xml</tt> on the object you want to render, since <tt>render</tt> will
- # automatically do that for you:
- #
- # # Also renders '<name>David</name>'
- # render :xml => {:name => "David"}
- #
- # === Rendering JSON
- #
- # Rendering JSON sets the content type to application/json and optionally wraps the JSON in a callback. It is expected
- # that the response will be parsed (or eval'd) for use as a data structure.
- #
- # # Renders '{"name": "David"}'
- # render :json => {:name => "David"}.to_json
- #
- # It's not necessary to call <tt>to_json</tt> on the object you want to render, since <tt>render</tt> will
- # automatically do that for you:
- #
- # # Also renders '{"name": "David"}'
- # render :json => {:name => "David"}
- #
- # Sometimes the result isn't handled directly by a script (such as when the request comes from a SCRIPT tag),
- # so the <tt>:callback</tt> option is provided for these cases.
- #
- # # Renders 'show({"name": "David"})'
- # render :json => {:name => "David"}.to_json, :callback => 'show'
- #
- # === Rendering an inline template
- #
- # Rendering of an inline template works as a cross between text and action rendering where the source for the template
- # is supplied inline, like text, but its interpreted with ERb or Builder, like action. By default, ERb is used for rendering
- # and the current layout is not used.
- #
- # # Renders "hello, hello, hello, again"
- # render :inline => "<%= 'hello, ' * 3 + 'again' %>"
- #
- # # Renders "<p>Good seeing you!</p>" using Builder
- # render :inline => "xml.p { 'Good seeing you!' }", :type => :builder
- #
- # # Renders "hello david"
- # render :inline => "<%= 'hello ' + name %>", :locals => { :name => "david" }
- #
- # === Rendering inline JavaScriptGenerator page updates
- #
- # In addition to rendering JavaScriptGenerator page updates with Ajax in RJS templates (see ActionView::Base for details),
- # you can also pass the <tt>:update</tt> parameter to +render+, along with a block, to render page updates inline.
- #
- # render :update do |page|
- # page.replace_html 'user_list', :partial => 'user', :collection => @users
- # page.visual_effect :highlight, 'user_list'
- # end
- #
- # === Rendering vanilla JavaScript
- #
- # In addition to using RJS with render :update, you can also just render vanilla JavaScript with :js.
- #
- # # Renders "alert('hello')" and sets the mime type to text/javascript
- # render :js => "alert('hello')"
- #
- # === Rendering with status and location headers
- # All renders take the <tt>:status</tt> and <tt>:location</tt> options and turn them into headers. They can even be used together:
- #
- # render :xml => post.to_xml, :status => :created, :location => post_url(post)
- def render(options = nil, extra_options = {}, &block) #:doc:
- raise DoubleRenderError, "Can only render or redirect once per action" if performed?
-
- options = { :layout => true } if options.nil?
- original, options = options, extra_options unless options.is_a?(Hash)
-
- layout_name = options.delete(:layout)
-
- _process_options(options)
-
- if block_given?
- @template.send(:_evaluate_assigns_and_ivars)
-
- generator = ActionView::Helpers::PrototypeHelper::JavaScriptGenerator.new(@template, &block)
- response.content_type = Mime::JS
- return render_for_text(generator.to_s)
- end
-
- if original
- return render_for_name(original, layout_name, options) unless block_given?
- end
-
- if options.key?(:text)
- return render_for_text(@template._render_text(options[:text],
- _pick_layout(layout_name), options))
- end
-
- file, template = options.values_at(:file, :template)
- if file || template
- file = template.sub(/^\//, '') if template
- return render_for_file(file, [layout_name, !!template], options)
- end
-
- if action_option = options[:action]
- return render_for_action(action_option, [layout_name, true], options)
- end
-
- if inline = options[:inline]
- render_for_text(@template._render_inline(inline, _pick_layout(layout_name), options))
-
- elsif xml = options[:xml]
- response.content_type ||= Mime::XML
- render_for_text(xml.respond_to?(:to_xml) ? xml.to_xml : xml)
-
- elsif js = options[:js]
- response.content_type ||= Mime::JS
- render_for_text(js)
-
- elsif json = options[:json]
- json = json.to_json unless json.is_a?(String)
- json = "#{options[:callback]}(#{json})" unless options[:callback].blank?
- response.content_type ||= Mime::JSON
- render_for_text(json)
-
- elsif partial = options[:partial]
- if partial == true
- parts = [action_name_base, formats, controller_name, true]
- elsif partial.is_a?(String)
- parts = partial_parts(partial, options)
- else
- return render_for_text(@template._render_partial(options))
- end
-
- render_for_parts(parts, layout_name, options)
-
- elsif options[:nothing]
- render_for_text(nil)
-
- else
- render_for_parts([action_name, formats, controller_path], layout_name, options)
- end
- end
-
- def formats
- @_request.formats.map {|f| f.symbol }.compact
- end
-
- def action_name_base(name = action_name)
- (name.is_a?(String) ? name.sub(/^#{controller_path}\//, '') : name).to_s
- end
-
- # Renders according to the same rules as <tt>render</tt>, but returns the result in a string instead
- # of sending it as the response body to the browser.
- def render_to_string(options = nil, &block) #:doc:
- render(options, &block)
- ensure
- response.content_type = nil
- erase_render_results
- reset_variables_added_to_assigns
- end
-
- # Return a response that has no content (merely headers). The options
- # argument is interpreted to be a hash of header names and values.
- # This allows you to easily return a response that consists only of
- # significant headers:
- #
- # head :created, :location => person_path(@person)
- #
- # It can also be used to return exceptional conditions:
- #
- # return head(:method_not_allowed) unless request.post?
- # return head(:bad_request) unless valid_request?
- # render
- def head(*args)
- if args.length > 2
- raise ArgumentError, "too many arguments to head"
- elsif args.empty?
- raise ArgumentError, "too few arguments to head"
- end
- options = args.extract_options!
- status = interpret_status(args.shift || options.delete(:status) || :ok)
-
- options.each do |key, value|
- headers[key.to_s.dasherize.split(/-/).map { |v| v.capitalize }.join("-")] = value.to_s
- end
-
- 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
- @performed_render = false
- end
-
- # Clears the redirected results from the headers, resets the status to 200 and returns
- # the URL that was used to redirect or nil if there was no redirected URL
- # Note that +redirect_to+ will change the body of the response to indicate a redirection.
- # The response body is not reset here, see +erase_render_results+
- def erase_redirect_results #:nodoc:
- @performed_redirect = false
- response.redirected_to = nil
- response.redirected_to_method_params = nil
- response.status = DEFAULT_RENDER_STATUS_CODE
- response.headers.delete('Location')
- end
-
- # Erase both render and redirect results
- def erase_results #:nodoc:
- erase_render_results
- erase_redirect_results
- end
-
def rewrite_options(options) #:nodoc:
if defaults = default_url_options(options)
defaults.merge(options)
@@ -1024,73 +685,6 @@ module ActionController #:nodoc:
def default_url_options(options = nil)
end
- # Redirects the browser to the target specified in +options+. This parameter can take one of three forms:
- #
- # * <tt>Hash</tt> - The URL will be generated by calling url_for with the +options+.
- # * <tt>Record</tt> - The URL will be generated by calling url_for with the +options+, which will reference a named URL for that record.
- # * <tt>String</tt> starting with <tt>protocol://</tt> (like <tt>http://</tt>) - Is passed straight through as the target for redirection.
- # * <tt>String</tt> not containing a protocol - The current protocol and host is prepended to the string.
- # * <tt>:back</tt> - Back to the page that issued the request. Useful for forms that are triggered from multiple places.
- # Short-hand for <tt>redirect_to(request.env["HTTP_REFERER"])</tt>
- #
- # Examples:
- # redirect_to :action => "show", :id => 5
- # redirect_to post
- # redirect_to "http://www.rubyonrails.org"
- # redirect_to "/images/screenshot.jpg"
- # redirect_to articles_url
- # redirect_to :back
- #
- # The redirection happens as a "302 Moved" header unless otherwise specified.
- #
- # Examples:
- # redirect_to post_url(@post), :status=>:found
- # redirect_to :action=>'atom', :status=>:moved_permanently
- # redirect_to post_url(@post), :status=>301
- # redirect_to :action=>'atom', :status=>302
- #
- # 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:
- 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
- end
-
- response.redirected_to = options
- logger.info("Redirected to #{options}") if logger && logger.info?
-
- case options
- # The scheme name consist of a letter followed by any combination of
- # letters, digits, and the plus ("+"), period ("."), or hyphen ("-")
- # characters; and is terminated by a colon (":").
- when %r{^\w[\w\d+.-]*:.*}
- redirect_to_full_url(options, status)
- when String
- redirect_to_full_url(request.protocol + request.host_with_port + options, status)
- when :back
- if referer = request.headers["Referer"]
- redirect_to(referer, :status=>status)
- else
- raise RedirectBackError
- end
- else
- 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,
@@ -1178,71 +772,6 @@ module ActionController #:nodoc:
response.status = interpret_status(options[:status] || DEFAULT_RENDER_STATUS_CODE)
end
- def render_for_name(name, layout, options)
- case name.to_s.index('/')
- when 0
- render_for_file(name, layout, options)
- when nil
- render_for_action(name, layout, options)
- else
- render_for_file(name.sub(/^\//, ''), [layout, true], options)
- end
- end
-
- def render_for_parts(parts, layout, options = {})
- tmp = view_paths.find_by_parts(*parts)
- layout = _pick_layout(*layout) unless tmp.exempt_from_layout?
-
- render_for_text(
- @template._render_template_with_layout(tmp, layout, options, parts[3]))
- end
-
- def partial_parts(name, options)
- segments = name.split("/")
- parts = segments.pop.split(".")
-
- case parts.size
- when 1
- parts
- when 2, 3
- extension = parts.delete_at(1).to_sym
- if formats.include?(extension)
- self.formats.replace [extension]
- end
- parts.pop if parts.size == 2
- end
-
- path = parts.join(".")
- prefix = segments[0..-1].join("/")
- prefix = prefix.blank? ? controller_path : prefix
- parts = [path, formats, prefix]
- parts.push options[:object] || true
- end
-
- def render_for_file(file, layout, options)
- render_for_parts([file, [request.format.to_sym]], layout, options)
- end
-
- def render_for_action(name, layout, options)
- parts = [action_name_base(name), formats, controller_name]
- render_for_parts(parts, layout, options)
- end
-
- def render_for_text(text = nil, append_response = false) #:nodoc:
- @performed_render = true
-
- if append_response
- response.body ||= ''
- response.body << text.to_s
- else
- 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)
@template = response.template = ActionView::Base.new(self.class.view_paths, {}, self, formats)
response.template.helpers.send :include, self.class.master_helper_module
@@ -1318,22 +847,6 @@ module ActionController #:nodoc:
@action_name = (params['action'] || 'index')
end
- def action_methods
- self.class.action_methods
- end
-
- def self.action_methods
- @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
@@ -1363,14 +876,13 @@ module ActionController #:nodoc:
action_name = strip_out_controller(action_name)
end
end
- "#{self.controller_path}/#{action_name}"
+ "#{controller_path}/#{action_name}"
end
def strip_out_controller(path)
path.split('/', 2).last
end
-
def template_path_includes_controller?(path)
self.controller_path.split('/')[-1] == path.split('/')[0]
end
@@ -1381,7 +893,7 @@ module ActionController #:nodoc:
end
Base.class_eval do
- [ Filters, Layout, Benchmarking, Rescue, Flash, MimeResponds, Helpers,
+ [ Filters, Layout, Renderer, Redirector, Responder, Benchmarking, Rescue, Flash, MimeResponds, Helpers,
Cookies, Caching, Verification, Streaming, SessionManagement,
HttpAuthentication::Basic::ControllerMethods, RecordIdentifier,
RequestForgeryProtection, Translation
diff --git a/actionpack/lib/action_controller/benchmarking.rb b/actionpack/lib/action_controller/base/chained/benchmarking.rb
index 47377e5fa9..066150f58a 100644
--- a/actionpack/lib/action_controller/benchmarking.rb
+++ b/actionpack/lib/action_controller/base/chained/benchmarking.rb
@@ -64,7 +64,7 @@ module ActionController #:nodoc:
private
def perform_action_with_benchmark
- if logger
+ if logger && logger.info?
ms = [Benchmark.ms { perform_action_without_benchmark }, 0.01].max
logging_view = defined?(@view_runtime)
logging_active_record = Object.const_defined?("ActiveRecord") && ActiveRecord::Base.connected?
diff --git a/actionpack/lib/action_controller/filters.rb b/actionpack/lib/action_controller/base/chained/filters.rb
index 9022b8b279..9022b8b279 100644
--- a/actionpack/lib/action_controller/filters.rb
+++ b/actionpack/lib/action_controller/base/chained/filters.rb
diff --git a/actionpack/lib/action_controller/flash.rb b/actionpack/lib/action_controller/base/chained/flash.rb
index 56ee9c67e2..56ee9c67e2 100644
--- a/actionpack/lib/action_controller/flash.rb
+++ b/actionpack/lib/action_controller/base/chained/flash.rb
diff --git a/actionpack/lib/action_controller/cookies.rb b/actionpack/lib/action_controller/base/cookies.rb
index 840ceb5abd..840ceb5abd 100644
--- a/actionpack/lib/action_controller/cookies.rb
+++ b/actionpack/lib/action_controller/base/cookies.rb
diff --git a/actionpack/lib/action_controller/headers.rb b/actionpack/lib/action_controller/base/headers.rb
index 139669c66f..139669c66f 100644
--- a/actionpack/lib/action_controller/headers.rb
+++ b/actionpack/lib/action_controller/base/headers.rb
diff --git a/actionpack/lib/action_controller/helpers.rb b/actionpack/lib/action_controller/base/helpers.rb
index ba65032f6a..ba65032f6a 100644
--- a/actionpack/lib/action_controller/helpers.rb
+++ b/actionpack/lib/action_controller/base/helpers.rb
diff --git a/actionpack/lib/action_controller/http_authentication.rb b/actionpack/lib/action_controller/base/http_authentication.rb
index 2ed810db7d..2ed810db7d 100644
--- a/actionpack/lib/action_controller/http_authentication.rb
+++ b/actionpack/lib/action_controller/base/http_authentication.rb
diff --git a/actionpack/lib/action_controller/layout.rb b/actionpack/lib/action_controller/base/layout.rb
index 926ae26f92..926ae26f92 100644
--- a/actionpack/lib/action_controller/layout.rb
+++ b/actionpack/lib/action_controller/base/layout.rb
diff --git a/actionpack/lib/action_controller/base/redirect.rb b/actionpack/lib/action_controller/base/redirect.rb
new file mode 100644
index 0000000000..83af793978
--- /dev/null
+++ b/actionpack/lib/action_controller/base/redirect.rb
@@ -0,0 +1,91 @@
+module ActionController
+ class RedirectBackError < ActionControllerError #:nodoc:
+ DEFAULT_MESSAGE = 'No HTTP_REFERER was set in the request to this action, so redirect_to :back could not be called successfully. If this is a test, make sure to specify request.env["HTTP_REFERER"].'
+
+ def initialize(message = nil)
+ super(message || DEFAULT_MESSAGE)
+ end
+ end
+
+ module Redirector
+
+ # Redirects the browser to the target specified in +options+. This parameter can take one of three forms:
+ #
+ # * <tt>Hash</tt> - The URL will be generated by calling url_for with the +options+.
+ # * <tt>Record</tt> - The URL will be generated by calling url_for with the +options+, which will reference a named URL for that record.
+ # * <tt>String</tt> starting with <tt>protocol://</tt> (like <tt>http://</tt>) - Is passed straight through as the target for redirection.
+ # * <tt>String</tt> not containing a protocol - The current protocol and host is prepended to the string.
+ # * <tt>:back</tt> - Back to the page that issued the request. Useful for forms that are triggered from multiple places.
+ # Short-hand for <tt>redirect_to(request.env["HTTP_REFERER"])</tt>
+ #
+ # Examples:
+ # redirect_to :action => "show", :id => 5
+ # redirect_to post
+ # redirect_to "http://www.rubyonrails.org"
+ # redirect_to "/images/screenshot.jpg"
+ # redirect_to articles_url
+ # redirect_to :back
+ #
+ # The redirection happens as a "302 Moved" header unless otherwise specified.
+ #
+ # Examples:
+ # redirect_to post_url(@post), :status=>:found
+ # redirect_to :action=>'atom', :status=>:moved_permanently
+ # redirect_to post_url(@post), :status=>301
+ # redirect_to :action=>'atom', :status=>302
+ #
+ # 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:
+ 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
+ end
+
+ response.redirected_to = options
+ logger.info("Redirected to #{options}") if logger && logger.info?
+
+ case options
+ # The scheme name consist of a letter followed by any combination of
+ # letters, digits, and the plus ("+"), period ("."), or hyphen ("-")
+ # characters; and is terminated by a colon (":").
+ when %r{^\w[\w\d+.-]*:.*}
+ redirect_to_full_url(options, status)
+ when String
+ redirect_to_full_url(request.protocol + request.host_with_port + options, status)
+ when :back
+ if referer = request.headers["Referer"]
+ redirect_to(referer, :status=>status)
+ else
+ raise RedirectBackError
+ end
+ else
+ 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
+
+ # Clears the redirected results from the headers, resets the status to 200 and returns
+ # the URL that was used to redirect or nil if there was no redirected URL
+ # Note that +redirect_to+ will change the body of the response to indicate a redirection.
+ # The response body is not reset here, see +erase_render_results+
+ def erase_redirect_results #:nodoc:
+ @performed_redirect = false
+ response.redirected_to = nil
+ response.redirected_to_method_params = nil
+ response.status = DEFAULT_RENDER_STATUS_CODE
+ response.headers.delete('Location')
+ end
+ end
+end \ No newline at end of file
diff --git a/actionpack/lib/action_controller/base/render.rb b/actionpack/lib/action_controller/base/render.rb
new file mode 100644
index 0000000000..abba059969
--- /dev/null
+++ b/actionpack/lib/action_controller/base/render.rb
@@ -0,0 +1,378 @@
+module ActionController
+ DEFAULT_RENDER_STATUS_CODE = "200 OK"
+
+ class DoubleRenderError < ActionControllerError #:nodoc:
+ DEFAULT_MESSAGE = "Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like \"redirect_to(...) and return\"."
+
+ def initialize(message = nil)
+ super(message || DEFAULT_MESSAGE)
+ end
+ end
+
+ module Renderer
+
+ protected
+ # Renders the content that will be returned to the browser as the response body.
+ #
+ # === Rendering an action
+ #
+ # Action rendering is the most common form and the type used automatically by Action Controller when nothing else is
+ # specified. By default, actions are rendered within the current layout (if one exists).
+ #
+ # # Renders the template for the action "goal" within the current controller
+ # render :action => "goal"
+ #
+ # # Renders the template for the action "short_goal" within the current controller,
+ # # but without the current active layout
+ # render :action => "short_goal", :layout => false
+ #
+ # # Renders the template for the action "long_goal" within the current controller,
+ # # but with a custom layout
+ # render :action => "long_goal", :layout => "spectacular"
+ #
+ # === Rendering partials
+ #
+ # Partial rendering in a controller is most commonly used together with Ajax calls that only update one or a few elements on a page
+ # without reloading. Rendering of partials from the controller makes it possible to use the same partial template in
+ # both the full-page rendering (by calling it from within the template) and when sub-page updates happen (from the
+ # controller action responding to Ajax calls). By default, the current layout is not used.
+ #
+ # # Renders the same partial with a local variable.
+ # render :partial => "person", :locals => { :name => "david" }
+ #
+ # # Renders the partial, making @new_person available through
+ # # the local variable 'person'
+ # render :partial => "person", :object => @new_person
+ #
+ # # Renders a collection of the same partial by making each element
+ # # of @winners available through the local variable "person" as it
+ # # 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"
+ #
+ # # Renders a collection of partials located in a view subfolder
+ # # outside of our current controller. In this example we will be
+ # # rendering app/views/shared/_note.r(html|xml) Inside the partial
+ # # each element of @new_notes is available as the local var "note".
+ # render :partial => "shared/note", :collection => @new_notes
+ #
+ # # Renders the partial with a status code of 500 (internal error).
+ # render :partial => "broken", :status => 500
+ #
+ # Note that the partial filename must also be a valid Ruby variable name,
+ # so e.g. 2005 and register-user are invalid.
+ #
+ #
+ # == Automatic etagging
+ #
+ # Rendering will automatically insert the etag header on 200 OK responses. The etag is calculated using MD5 of the
+ # response body. If a request comes in that has a matching etag, the response will be changed to a 304 Not Modified
+ # and the response body will be set to an empty string. No etag header will be inserted if it's already set.
+ #
+ # === Rendering a template
+ #
+ # Template rendering works just like action rendering except that it takes a path relative to the template root.
+ # The current layout is automatically applied.
+ #
+ # # Renders the template located in [TEMPLATE_ROOT]/weblog/show.r(html|xml) (in Rails, app/views/weblog/show.erb)
+ # render :template => "weblog/show"
+ #
+ # # Renders the template with a local variable
+ # render :template => "weblog/show", :locals => {:customer => Customer.new}
+ #
+ # === Rendering a file
+ #
+ # File rendering works just like action rendering except that it takes a filesystem path. By default, the path
+ # is assumed to be absolute, and the current layout is not applied.
+ #
+ # # Renders the template located at the absolute filesystem path
+ # render :file => "/path/to/some/template.erb"
+ # render :file => "c:/path/to/some/template.erb"
+ #
+ # # Renders a template within the current layout, and with a 404 status code
+ # render :file => "/path/to/some/template.erb", :layout => true, :status => 404
+ # render :file => "c:/path/to/some/template.erb", :layout => true, :status => 404
+ #
+ # === Rendering text
+ #
+ # Rendering of text is usually used for tests or for rendering prepared content, such as a cache. By default, text
+ # rendering is not done within the active layout.
+ #
+ # # Renders the clear text "hello world" with status code 200
+ # render :text => "hello world!"
+ #
+ # # Renders the clear text "Explosion!" with status code 500
+ # render :text => "Explosion!", :status => 500
+ #
+ # # Renders the clear text "Hi there!" within the current active layout (if one exists)
+ # render :text => "Hi there!", :layout => true
+ #
+ # # Renders the clear text "Hi there!" within the layout
+ # # placed in "app/views/layouts/special.r(html|xml)"
+ # render :text => "Hi there!", :layout => "special"
+ #
+ # The <tt>:text</tt> option can also accept a Proc object, which can be used to manually control the page generation. This should
+ # generally be avoided, as it violates the separation between code and content, and because almost everything that can be
+ # done with this method can also be done more cleanly using one of the other rendering methods, most notably templates.
+ #
+ # # Renders "Hello from code!"
+ # render :text => proc { |response, output| output.write("Hello from code!") }
+ #
+ # === Rendering XML
+ #
+ # Rendering XML sets the content type to application/xml.
+ #
+ # # Renders '<name>David</name>'
+ # render :xml => {:name => "David"}.to_xml
+ #
+ # It's not necessary to call <tt>to_xml</tt> on the object you want to render, since <tt>render</tt> will
+ # automatically do that for you:
+ #
+ # # Also renders '<name>David</name>'
+ # render :xml => {:name => "David"}
+ #
+ # === Rendering JSON
+ #
+ # Rendering JSON sets the content type to application/json and optionally wraps the JSON in a callback. It is expected
+ # that the response will be parsed (or eval'd) for use as a data structure.
+ #
+ # # Renders '{"name": "David"}'
+ # render :json => {:name => "David"}.to_json
+ #
+ # It's not necessary to call <tt>to_json</tt> on the object you want to render, since <tt>render</tt> will
+ # automatically do that for you:
+ #
+ # # Also renders '{"name": "David"}'
+ # render :json => {:name => "David"}
+ #
+ # Sometimes the result isn't handled directly by a script (such as when the request comes from a SCRIPT tag),
+ # so the <tt>:callback</tt> option is provided for these cases.
+ #
+ # # Renders 'show({"name": "David"})'
+ # render :json => {:name => "David"}.to_json, :callback => 'show'
+ #
+ # === Rendering an inline template
+ #
+ # Rendering of an inline template works as a cross between text and action rendering where the source for the template
+ # is supplied inline, like text, but its interpreted with ERb or Builder, like action. By default, ERb is used for rendering
+ # and the current layout is not used.
+ #
+ # # Renders "hello, hello, hello, again"
+ # render :inline => "<%= 'hello, ' * 3 + 'again' %>"
+ #
+ # # Renders "<p>Good seeing you!</p>" using Builder
+ # render :inline => "xml.p { 'Good seeing you!' }", :type => :builder
+ #
+ # # Renders "hello david"
+ # render :inline => "<%= 'hello ' + name %>", :locals => { :name => "david" }
+ #
+ # === Rendering inline JavaScriptGenerator page updates
+ #
+ # In addition to rendering JavaScriptGenerator page updates with Ajax in RJS templates (see ActionView::Base for details),
+ # you can also pass the <tt>:update</tt> parameter to +render+, along with a block, to render page updates inline.
+ #
+ # render :update do |page|
+ # page.replace_html 'user_list', :partial => 'user', :collection => @users
+ # page.visual_effect :highlight, 'user_list'
+ # end
+ #
+ # === Rendering vanilla JavaScript
+ #
+ # In addition to using RJS with render :update, you can also just render vanilla JavaScript with :js.
+ #
+ # # Renders "alert('hello')" and sets the mime type to text/javascript
+ # render :js => "alert('hello')"
+ #
+ # === Rendering with status and location headers
+ # All renders take the <tt>:status</tt> and <tt>:location</tt> options and turn them into headers. They can even be used together:
+ #
+ # render :xml => post.to_xml, :status => :created, :location => post_url(post)
+ def render(options = nil, extra_options = {}, &block) #:doc:
+ raise DoubleRenderError, "Can only render or redirect once per action" if performed?
+
+ options = { :layout => true } if options.nil?
+ original, options = options, extra_options unless options.is_a?(Hash)
+
+ layout_name = options.delete(:layout)
+
+ _process_options(options)
+
+ if block_given?
+ @template.send(:_evaluate_assigns_and_ivars)
+
+ generator = ActionView::Helpers::PrototypeHelper::JavaScriptGenerator.new(@template, &block)
+ response.content_type = Mime::JS
+ return render_for_text(generator.to_s)
+ end
+
+ if original
+ return render_for_name(original, layout_name, options) unless block_given?
+ end
+
+ if options.key?(:text)
+ return render_for_text(@template._render_text(options[:text],
+ _pick_layout(layout_name), options))
+ end
+
+ file, template = options.values_at(:file, :template)
+ if file || template
+ file = template.sub(/^\//, '') if template
+ return render_for_file(file, [layout_name, !!template], options)
+ end
+
+ if action_option = options[:action]
+ return render_for_action(action_option, [layout_name, true], options)
+ end
+
+ if inline = options[:inline]
+ render_for_text(@template._render_inline(inline, _pick_layout(layout_name), options))
+
+ elsif xml = options[:xml]
+ response.content_type ||= Mime::XML
+ render_for_text(xml.respond_to?(:to_xml) ? xml.to_xml : xml)
+
+ elsif js = options[:js]
+ response.content_type ||= Mime::JS
+ render_for_text(js)
+
+ elsif json = options[:json]
+ json = json.to_json unless json.is_a?(String)
+ json = "#{options[:callback]}(#{json})" unless options[:callback].blank?
+ response.content_type ||= Mime::JSON
+ render_for_text(json)
+
+ elsif partial = options[:partial]
+ if partial == true
+ parts = [action_name_base, formats, controller_name, true]
+ elsif partial.is_a?(String)
+ parts = partial_parts(partial, options)
+ else
+ return render_for_text(@template._render_partial(options))
+ end
+
+ render_for_parts(parts, layout_name, options)
+
+ elsif options[:nothing]
+ render_for_text(nil)
+
+ else
+ render_for_parts([action_name, formats, controller_path], layout_name, options)
+ end
+ end
+
+ def partial_parts(name, options)
+ segments = name.split("/")
+ parts = segments.pop.split(".")
+
+ case parts.size
+ when 1
+ parts
+ when 2, 3
+ extension = parts.delete_at(1).to_sym
+ if formats.include?(extension)
+ self.formats.replace [extension]
+ end
+ parts.pop if parts.size == 2
+ end
+
+ path = parts.join(".")
+ prefix = segments[0..-1].join("/")
+ prefix = prefix.blank? ? controller_path : prefix
+ parts = [path, formats, prefix]
+ parts.push options[:object] || true
+ end
+
+ def formats
+ @_request.formats.map {|f| f.symbol }.compact
+ end
+
+ def action_name_base(name = action_name)
+ (name.is_a?(String) ? name.sub(/^#{controller_path}\//, '') : name).to_s
+ end
+
+ # Renders according to the same rules as <tt>render</tt>, but returns the result in a string instead
+ # of sending it as the response body to the browser.
+ def render_to_string(options = nil, &block) #:doc:
+ render(options, &block)
+ ensure
+ response.content_type = nil
+ erase_render_results
+ reset_variables_added_to_assigns
+ end
+
+ # Clears the rendered results, allowing for another render to be performed.
+ def erase_render_results #:nodoc:
+ response.body = nil
+ @performed_render = false
+ end
+
+ # Erase both render and redirect results
+ def erase_results #:nodoc:
+ erase_render_results
+ erase_redirect_results
+ end
+
+ # Return a response that has no content (merely headers). The options
+ # argument is interpreted to be a hash of header names and values.
+ # This allows you to easily return a response that consists only of
+ # significant headers:
+ #
+ # head :created, :location => person_path(@person)
+ #
+ # It can also be used to return exceptional conditions:
+ #
+ # return head(:method_not_allowed) unless request.post?
+ # return head(:bad_request) unless valid_request?
+ # render
+ def head(*args)
+ if args.length > 2
+ raise ArgumentError, "too many arguments to head"
+ elsif args.empty?
+ raise ArgumentError, "too few arguments to head"
+ end
+ options = args.extract_options!
+ status = interpret_status(args.shift || options.delete(:status) || :ok)
+
+ options.each do |key, value|
+ headers[key.to_s.dasherize.split(/-/).map { |v| v.capitalize }.join("-")] = value.to_s
+ end
+
+ render :nothing => true, :status => status
+ end
+
+ private
+ def render_for_name(name, layout, options)
+ case name.to_s.index('/')
+ when 0
+ render_for_file(name, layout, options)
+ when nil
+ render_for_action(name, layout, options)
+ else
+ render_for_file(name.sub(/^\//, ''), [layout, true], options)
+ end
+ end
+
+ def render_for_parts(parts, layout, options = {})
+ tmp = view_paths.find_by_parts(*parts)
+ layout = _pick_layout(*layout) unless tmp.exempt_from_layout?
+
+ render_for_text(
+ @template._render_template_with_layout(tmp, layout, options, parts[3]))
+ end
+
+ def render_for_file(file, layout, options)
+ render_for_parts([file, [request.format.to_sym]], layout, options)
+ end
+
+ def render_for_action(name, layout, options)
+ parts = [action_name_base(name), formats, controller_name]
+ render_for_parts(parts, layout, options)
+ end
+ end
+end \ No newline at end of file
diff --git a/actionpack/lib/action_controller/request_forgery_protection.rb b/actionpack/lib/action_controller/base/request_forgery_protection.rb
index f3e6288c26..f3e6288c26 100644
--- a/actionpack/lib/action_controller/request_forgery_protection.rb
+++ b/actionpack/lib/action_controller/base/request_forgery_protection.rb
diff --git a/actionpack/lib/action_controller/base/responder.rb b/actionpack/lib/action_controller/base/responder.rb
new file mode 100644
index 0000000000..f83abb5a4b
--- /dev/null
+++ b/actionpack/lib/action_controller/base/responder.rb
@@ -0,0 +1,41 @@
+module ActionController
+ module Responder
+ def self.included(klass)
+ klass.extend ClassMethods
+ end
+
+ private
+ def render_for_text(text = nil, append_response = false) #:nodoc:
+ @performed_render = true
+
+ if append_response
+ response.body ||= ''
+ response.body << text.to_s
+ else
+ 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 action_methods
+ self.class.action_methods
+ end
+
+ module ClassMethods
+ def action_methods
+ @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
+ end
+ end
+end \ No newline at end of file
diff --git a/actionpack/lib/action_controller/streaming.rb b/actionpack/lib/action_controller/base/streaming.rb
index e1786913a7..e1786913a7 100644
--- a/actionpack/lib/action_controller/streaming.rb
+++ b/actionpack/lib/action_controller/base/streaming.rb
diff --git a/actionpack/lib/action_controller/verification.rb b/actionpack/lib/action_controller/base/verification.rb
index 7bf09ba6ea..7bf09ba6ea 100644
--- a/actionpack/lib/action_controller/verification.rb
+++ b/actionpack/lib/action_controller/base/verification.rb
diff --git a/actionpack/lib/action_controller/cgi_ext.rb b/actionpack/lib/action_controller/cgi/ext.rb
index 406b6f06d6..558748f4bd 100644
--- a/actionpack/lib/action_controller/cgi_ext.rb
+++ b/actionpack/lib/action_controller/cgi/ext.rb
@@ -1,6 +1,6 @@
-require 'action_controller/cgi_ext/stdinput'
-require 'action_controller/cgi_ext/query_extension'
-require 'action_controller/cgi_ext/cookie'
+require 'action_controller/cgi/ext/stdinput'
+require 'action_controller/cgi/ext/query_extension'
+require 'action_controller/cgi/ext/cookie'
class CGI #:nodoc:
include ActionController::CgiExt::Stdinput
diff --git a/actionpack/lib/action_controller/cgi_ext/cookie.rb b/actionpack/lib/action_controller/cgi/ext/cookie.rb
index 9cd19bb12d..9cd19bb12d 100644
--- a/actionpack/lib/action_controller/cgi_ext/cookie.rb
+++ b/actionpack/lib/action_controller/cgi/ext/cookie.rb
diff --git a/actionpack/lib/action_controller/cgi_ext/query_extension.rb b/actionpack/lib/action_controller/cgi/ext/query_extension.rb
index 9620fd2873..9620fd2873 100644
--- a/actionpack/lib/action_controller/cgi_ext/query_extension.rb
+++ b/actionpack/lib/action_controller/cgi/ext/query_extension.rb
diff --git a/actionpack/lib/action_controller/cgi_ext/stdinput.rb b/actionpack/lib/action_controller/cgi/ext/stdinput.rb
index 5e9b6784af..5e9b6784af 100644
--- a/actionpack/lib/action_controller/cgi_ext/stdinput.rb
+++ b/actionpack/lib/action_controller/cgi/ext/stdinput.rb
diff --git a/actionpack/lib/action_controller/cgi_process.rb b/actionpack/lib/action_controller/cgi/process.rb
index 7e5e95e135..ffcad5666a 100644
--- a/actionpack/lib/action_controller/cgi_process.rb
+++ b/actionpack/lib/action_controller/cgi/process.rb
@@ -1,5 +1,3 @@
-require 'action_controller/cgi_ext'
-
module ActionController #:nodoc:
class CGIHandler
module ProperStream
diff --git a/actionpack/lib/action_controller/dispatcher.rb b/actionpack/lib/action_controller/dispatch/dispatcher.rb
index 781bc48887..714e270781 100644
--- a/actionpack/lib/action_controller/dispatcher.rb
+++ b/actionpack/lib/action_controller/dispatch/dispatcher.rb
@@ -46,7 +46,7 @@ module ActionController
cattr_accessor :middleware
self.middleware = MiddlewareStack.new do |middleware|
- middlewares = File.join(File.dirname(__FILE__), "middlewares.rb")
+ middlewares = File.join(File.dirname(__FILE__), "rack", "middlewares.rb")
middleware.instance_eval(File.read(middlewares))
end
diff --git a/actionpack/lib/action_controller/params_parser.rb b/actionpack/lib/action_controller/dispatch/params_parser.rb
index d269fe07fa..d269fe07fa 100644
--- a/actionpack/lib/action_controller/params_parser.rb
+++ b/actionpack/lib/action_controller/dispatch/params_parser.rb
diff --git a/actionpack/lib/action_controller/failsafe.rb b/actionpack/lib/action_controller/dispatch/rack/failsafe.rb
index 567581142c..567581142c 100644
--- a/actionpack/lib/action_controller/failsafe.rb
+++ b/actionpack/lib/action_controller/dispatch/rack/failsafe.rb
diff --git a/actionpack/lib/action_controller/dispatch/rack/lock.rb b/actionpack/lib/action_controller/dispatch/rack/lock.rb
new file mode 100644
index 0000000000..c50762216e
--- /dev/null
+++ b/actionpack/lib/action_controller/dispatch/rack/lock.rb
@@ -0,0 +1,16 @@
+module ActionController
+ class Lock
+ FLAG = 'rack.multithread'.freeze
+
+ def initialize(app, lock = Mutex.new)
+ @app, @lock = app, lock
+ end
+
+ def call(env)
+ old, env[FLAG] = env[FLAG], false
+ @lock.synchronize { @app.call(env) }
+ ensure
+ env[FLAG] = old
+ end
+ end
+end
diff --git a/actionpack/lib/action_controller/middleware_stack.rb b/actionpack/lib/action_controller/dispatch/rack/middleware_stack.rb
index dbc2fda41e..dbc2fda41e 100644
--- a/actionpack/lib/action_controller/middleware_stack.rb
+++ b/actionpack/lib/action_controller/dispatch/rack/middleware_stack.rb
diff --git a/actionpack/lib/action_controller/middlewares.rb b/actionpack/lib/action_controller/dispatch/rack/middlewares.rb
index f9cfc2b18e..f9cfc2b18e 100644
--- a/actionpack/lib/action_controller/middlewares.rb
+++ b/actionpack/lib/action_controller/dispatch/rack/middlewares.rb
diff --git a/actionpack/lib/action_controller/request.rb b/actionpack/lib/action_controller/dispatch/request.rb
index f8c77241b9..f8c77241b9 100755
--- a/actionpack/lib/action_controller/request.rb
+++ b/actionpack/lib/action_controller/dispatch/request.rb
diff --git a/actionpack/lib/action_controller/dispatch/request_parser.rb b/actionpack/lib/action_controller/dispatch/request_parser.rb
new file mode 100644
index 0000000000..d1739ef4d0
--- /dev/null
+++ b/actionpack/lib/action_controller/dispatch/request_parser.rb
@@ -0,0 +1,315 @@
+module ActionController
+ class RequestParser
+ def initialize(env)
+ @env = env
+ freeze
+ end
+
+ def request_parameters
+ @env["action_controller.request_parser.request_parameters"] ||= parse_formatted_request_parameters
+ end
+
+ def query_parameters
+ @env["action_controller.request_parser.query_parameters"] ||= self.class.parse_query_parameters(query_string)
+ end
+
+ # Returns the query string, accounting for server idiosyncrasies.
+ def query_string
+ @env['QUERY_STRING'].present? ? @env['QUERY_STRING'] : (@env['REQUEST_URI'].split('?', 2)[1] || '')
+ end
+
+ # The request body is an IO input stream. If the RAW_POST_DATA environment
+ # 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
+ @env['rack.input']
+ end
+ end
+
+ # The raw content type string with its parameters stripped off.
+ def content_type_without_parameters
+ self.class.extract_content_type_without_parameters(content_type_with_parameters)
+ end
+
+ def raw_post
+ unless @env.include? 'RAW_POST_DATA'
+ @env['RAW_POST_DATA'] = body.read(content_length)
+ body.rewind if body.respond_to?(:rewind)
+ end
+ @env['RAW_POST_DATA']
+ end
+
+ private
+
+ def parse_formatted_request_parameters
+ return {} if content_length.zero?
+
+ content_type, boundary = self.class.extract_multipart_boundary(content_type_with_parameters)
+
+ # Don't parse params for unknown requests.
+ return {} if content_type.blank?
+
+ mime_type = Mime::Type.lookup(content_type)
+ strategy = ActionController::Base.param_parsers[mime_type]
+
+ # Only multipart form parsing expects a stream.
+ body = (strategy && strategy != :multipart_form) ? raw_post : self.body
+
+ case strategy
+ when Proc
+ strategy.call(body)
+ when :url_encoded_form
+ self.class.clean_up_ajax_request_body! body
+ self.class.parse_query_parameters(body)
+ when :multipart_form
+ self.class.parse_multipart_form_parameters(body, boundary, content_length, @env)
+ when :xml_simple, :xml_node
+ body.blank? ? {} : Hash.from_xml(body).with_indifferent_access
+ when :yaml
+ YAML.load(body)
+ when :json
+ if body.blank?
+ {}
+ else
+ data = ActiveSupport::JSON.decode(body)
+ data = {:_json => data} unless data.is_a?(Hash)
+ data.with_indifferent_access
+ end
+ else
+ {}
+ end
+ rescue Exception => e # YAML, XML or Ruby code block errors
+ raise
+ { "body" => body,
+ "content_type" => content_type_with_parameters,
+ "content_length" => content_length,
+ "exception" => "#{e.message} (#{e.class})",
+ "backtrace" => e.backtrace }
+ end
+
+ def content_length
+ @env['CONTENT_LENGTH'].to_i
+ end
+
+ # The raw content type string. Use when you need parameters such as
+ # charset or boundary which aren't included in the content_type MIME type.
+ # Overridden by the X-POST_DATA_FORMAT header for backward compatibility.
+ def content_type_with_parameters
+ content_type_from_legacy_post_data_format_header || @env['CONTENT_TYPE'].to_s
+ end
+
+ def content_type_from_legacy_post_data_format_header
+ if x_post_format = @env['HTTP_X_POST_DATA_FORMAT']
+ case x_post_format.to_s.downcase
+ when 'yaml'; 'application/x-yaml'
+ when 'xml'; 'application/xml'
+ end
+ end
+ end
+
+ class << self
+ def parse_query_parameters(query_string)
+ return {} if query_string.blank?
+
+ pairs = query_string.split('&').collect do |chunk|
+ next if chunk.empty?
+ key, value = chunk.split('=', 2)
+ next if key.empty?
+ value = value.nil? ? nil : CGI.unescape(value)
+ [ CGI.unescape(key), value ]
+ end.compact
+
+ UrlEncodedPairParser.new(pairs).result
+ end
+
+ def parse_request_parameters(params)
+ parser = UrlEncodedPairParser.new
+
+ params = params.dup
+ until params.empty?
+ for key, value in params
+ if key.blank?
+ params.delete key
+ elsif !key.include?('[')
+ # much faster to test for the most common case first (GET)
+ # and avoid the call to build_deep_hash
+ parser.result[key] = get_typed_value(value[0])
+ params.delete key
+ elsif value.is_a?(Array)
+ parser.parse(key, get_typed_value(value.shift))
+ params.delete key if value.empty?
+ else
+ raise TypeError, "Expected array, found #{value.inspect}"
+ end
+ end
+ end
+
+ parser.result
+ end
+
+ 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)
+ if content_type_with_parameters =~ MULTIPART_BOUNDARY
+ ['multipart/form-data', $1.dup]
+ else
+ extract_content_type_without_parameters(content_type_with_parameters)
+ end
+ end
+
+ def extract_content_type_without_parameters(content_type_with_parameters)
+ $1.strip.downcase if content_type_with_parameters =~ /^([^,\;]*)/
+ end
+
+ def clean_up_ajax_request_body!(body)
+ body.chop! if body[-1] == 0
+ body.gsub!(/&_=$/, '')
+ end
+
+
+ private
+ def get_typed_value(value)
+ case value
+ when String
+ value
+ when NilClass
+ ''
+ when Array
+ value.map { |v| get_typed_value(v) }
+ else
+ if value.respond_to? :original_filename
+ # Uploaded file
+ if value.original_filename
+ value
+ # Multipart param
+ else
+ result = value.read
+ value.rewind
+ result
+ end
+ # Unknown value, neither string nor multipart.
+ else
+ raise "Unknown form value: #{value.inspect}"
+ end
+ end
+ end
+
+ MULTIPART_BOUNDARY = %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|n
+
+ EOL = "\015\012"
+
+ def read_multipart(body, boundary, body_size, env)
+ params = Hash.new([])
+ boundary = "--" + boundary
+ quoted_boundary = Regexp.quote(boundary)
+ buf = ""
+ bufsize = 10 * 1024
+ boundary_end=""
+
+ # 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
+ body_size -= boundary_size
+ status = body.read(boundary_size)
+ if nil == status
+ raise EOFError, "no content body"
+ elsif boundary + EOL != status
+ raise EOFError, "bad content body"
+ end
+
+ loop do
+ head = nil
+ content =
+ if 10240 < body_size
+ UploadedTempfile.new("CGI")
+ else
+ UploadedStringIO.new
+ end
+ content.binmode if defined? content.binmode
+
+ until head and /#{quoted_boundary}(?:#{EOL}|--)/n.match(buf)
+
+ if (not head) and /#{EOL}#{EOL}/n.match(buf)
+ buf = buf.sub(/\A((?:.|\n)*?#{EOL})#{EOL}/n) do
+ head = $1.dup
+ ""
+ end
+ next
+ end
+
+ if head and ( (EOL + boundary + EOL).size < buf.size )
+ content.print buf[0 ... (buf.size - (EOL + boundary + EOL).size)]
+ buf[0 ... (buf.size - (EOL + boundary + EOL).size)] = ""
+ end
+
+ c = if bufsize < body_size
+ body.read(bufsize)
+ else
+ body.read(body_size)
+ end
+ if c.nil? || c.empty?
+ raise EOFError, "bad content body"
+ end
+ buf.concat(c)
+ 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
+ body_size = -1
+ end
+ boundary_end = $2.dup
+ ""
+ end
+
+ content.rewind
+
+ head =~ /Content-Disposition:.* filename=(?:"((?:\\.|[^\"])*)"|([^;]*))/ni
+ if filename = $1 || $2
+ if /Mac/ni.match(env['HTTP_USER_AGENT']) and
+ /Mozilla/ni.match(env['HTTP_USER_AGENT']) and
+ (not /MSIE/ni.match(env['HTTP_USER_AGENT']))
+ filename = CGI.unescape(filename)
+ end
+ content.original_path = filename.dup
+ end
+
+ head =~ /Content-Type: ([^\r]*)/ni
+ content.content_type = $1.dup if $1
+
+ head =~ /Content-Disposition:.* name="?([^\";]*)"?/ni
+ name = $1.dup if $1
+
+ if params.has_key?(name)
+ params[name].push(content)
+ else
+ params[name] = [content]
+ end
+ break if body_size == -1
+ end
+ raise EOFError, "bad boundary end of body part" unless boundary_end=~/--/
+
+ begin
+ body.rewind if body.respond_to?(:rewind)
+ rescue Errno::ESPIPE
+ # Handles exceptions raised by input streams that cannot be rewound
+ # such as when using plain CGI under Apache
+ end
+
+ params
+ end
+ end # class << self
+ end
+end
diff --git a/actionpack/lib/action_controller/rescue.rb b/actionpack/lib/action_controller/dispatch/rescue.rb
index 3beeb2da83..0293e62fc7 100644
--- a/actionpack/lib/action_controller/rescue.rb
+++ b/actionpack/lib/action_controller/dispatch/rescue.rb
@@ -60,8 +60,8 @@ module ActionController #:nodoc:
module ClassMethods
def call_with_exception(env, exception) #:nodoc:
- request = env["action_controller.rescue.request"] ||= Request.new(env)
- response = env["action_controller.rescue.response"] ||= Response.new
+ request = env["action_controller.rescue.request"] ||= ActionController::Request.new(env)
+ response = env["action_controller.rescue.response"] ||= ActionController::Response.new
new.process(request, response, :rescue_action, exception)
end
end
diff --git a/actionpack/lib/action_controller/response.rb b/actionpack/lib/action_controller/dispatch/response.rb
index 27860a6207..27860a6207 100644
--- a/actionpack/lib/action_controller/response.rb
+++ b/actionpack/lib/action_controller/dispatch/response.rb
diff --git a/actionpack/lib/action_controller/rewindable_input.rb b/actionpack/lib/action_controller/dispatch/rewindable_input.rb
index 36f655c51e..36f655c51e 100644
--- a/actionpack/lib/action_controller/rewindable_input.rb
+++ b/actionpack/lib/action_controller/dispatch/rewindable_input.rb
diff --git a/actionpack/lib/action_controller/status_codes.rb b/actionpack/lib/action_controller/dispatch/status_codes.rb
index 4977c79491..4977c79491 100644
--- a/actionpack/lib/action_controller/status_codes.rb
+++ b/actionpack/lib/action_controller/dispatch/status_codes.rb
diff --git a/actionpack/lib/action_controller/templates/rescues/_request_and_response.erb b/actionpack/lib/action_controller/dispatch/templates/rescues/_request_and_response.erb
index 64b34650b1..64b34650b1 100644
--- a/actionpack/lib/action_controller/templates/rescues/_request_and_response.erb
+++ b/actionpack/lib/action_controller/dispatch/templates/rescues/_request_and_response.erb
diff --git a/actionpack/lib/action_controller/templates/rescues/_trace.erb b/actionpack/lib/action_controller/dispatch/templates/rescues/_trace.erb
index bb2d8375bd..bb2d8375bd 100644
--- a/actionpack/lib/action_controller/templates/rescues/_trace.erb
+++ b/actionpack/lib/action_controller/dispatch/templates/rescues/_trace.erb
diff --git a/actionpack/lib/action_controller/templates/rescues/diagnostics.erb b/actionpack/lib/action_controller/dispatch/templates/rescues/diagnostics.erb
index 95be64511d..95be64511d 100644
--- a/actionpack/lib/action_controller/templates/rescues/diagnostics.erb
+++ b/actionpack/lib/action_controller/dispatch/templates/rescues/diagnostics.erb
diff --git a/actionpack/lib/action_controller/templates/rescues/layout.erb b/actionpack/lib/action_controller/dispatch/templates/rescues/layout.erb
index 4a04742e40..4a04742e40 100644
--- a/actionpack/lib/action_controller/templates/rescues/layout.erb
+++ b/actionpack/lib/action_controller/dispatch/templates/rescues/layout.erb
diff --git a/actionpack/lib/action_controller/templates/rescues/missing_template.erb b/actionpack/lib/action_controller/dispatch/templates/rescues/missing_template.erb
index dbfdf76947..dbfdf76947 100644
--- a/actionpack/lib/action_controller/templates/rescues/missing_template.erb
+++ b/actionpack/lib/action_controller/dispatch/templates/rescues/missing_template.erb
diff --git a/actionpack/lib/action_controller/templates/rescues/routing_error.erb b/actionpack/lib/action_controller/dispatch/templates/rescues/routing_error.erb
index ccfa858cce..ccfa858cce 100644
--- a/actionpack/lib/action_controller/templates/rescues/routing_error.erb
+++ b/actionpack/lib/action_controller/dispatch/templates/rescues/routing_error.erb
diff --git a/actionpack/lib/action_controller/templates/rescues/template_error.erb b/actionpack/lib/action_controller/dispatch/templates/rescues/template_error.erb
index 2e34e03bd5..2e34e03bd5 100644
--- a/actionpack/lib/action_controller/templates/rescues/template_error.erb
+++ b/actionpack/lib/action_controller/dispatch/templates/rescues/template_error.erb
diff --git a/actionpack/lib/action_controller/templates/rescues/unknown_action.erb b/actionpack/lib/action_controller/dispatch/templates/rescues/unknown_action.erb
index 683379da10..683379da10 100644
--- a/actionpack/lib/action_controller/templates/rescues/unknown_action.erb
+++ b/actionpack/lib/action_controller/dispatch/templates/rescues/unknown_action.erb
diff --git a/actionpack/lib/action_controller/uploaded_file.rb b/actionpack/lib/action_controller/dispatch/uploaded_file.rb
index 376ba3621a..376ba3621a 100644
--- a/actionpack/lib/action_controller/uploaded_file.rb
+++ b/actionpack/lib/action_controller/dispatch/uploaded_file.rb
diff --git a/actionpack/lib/action_controller/url_encoded_pair_parser.rb b/actionpack/lib/action_controller/dispatch/url_encoded_pair_parser.rb
index 57594c4259..57594c4259 100644
--- a/actionpack/lib/action_controller/url_encoded_pair_parser.rb
+++ b/actionpack/lib/action_controller/dispatch/url_encoded_pair_parser.rb
diff --git a/actionpack/lib/action_controller/mime_types.rb b/actionpack/lib/action_controller/mime/default_types.rb
index 2d7fba1173..2d7fba1173 100644
--- a/actionpack/lib/action_controller/mime_types.rb
+++ b/actionpack/lib/action_controller/mime/default_types.rb
diff --git a/actionpack/lib/action_controller/mime_responds.rb b/actionpack/lib/action_controller/mime/responds.rb
index bac225ab2a..bac225ab2a 100644
--- a/actionpack/lib/action_controller/mime_responds.rb
+++ b/actionpack/lib/action_controller/mime/responds.rb
diff --git a/actionpack/lib/action_controller/mime_type.rb b/actionpack/lib/action_controller/mime/type.rb
index 3d26870f4f..23a39dff54 100644
--- a/actionpack/lib/action_controller/mime_type.rb
+++ b/actionpack/lib/action_controller/mime/type.rb
@@ -211,4 +211,4 @@ module Mime
end
end
-require 'action_controller/mime_types'
+require 'action_controller/mime/default_types'
diff --git a/actionpack/lib/action_controller/record_identifier.rb b/actionpack/lib/action_controller/record_identifier.rb
index 742d290ad6..6bda27e23a 100644
--- a/actionpack/lib/action_controller/record_identifier.rb
+++ b/actionpack/lib/action_controller/record_identifier.rb
@@ -1,4 +1,4 @@
-module ActionController
+module ActionController
# The record identifier encapsulates a number of naming conventions for dealing with records, like Active Records or
# Active Resources or pretty much any other model type that has an id. These patterns are then used to try elevate
# the view actions to a higher logical level. Example:
diff --git a/actionpack/lib/action_controller/polymorphic_routes.rb b/actionpack/lib/action_controller/routing/generation/polymorphic_routes.rb
index 924d1aa6bd..924d1aa6bd 100644
--- a/actionpack/lib/action_controller/polymorphic_routes.rb
+++ b/actionpack/lib/action_controller/routing/generation/polymorphic_routes.rb
diff --git a/actionpack/lib/action_controller/url_rewriter.rb b/actionpack/lib/action_controller/routing/generation/url_rewriter.rb
index d86e2db67d..d86e2db67d 100644
--- a/actionpack/lib/action_controller/url_rewriter.rb
+++ b/actionpack/lib/action_controller/routing/generation/url_rewriter.rb
diff --git a/actionpack/lib/action_controller/resources.rb b/actionpack/lib/action_controller/routing/resources.rb
index e8988aa737..e8988aa737 100644
--- a/actionpack/lib/action_controller/resources.rb
+++ b/actionpack/lib/action_controller/routing/resources.rb
diff --git a/actionpack/lib/action_controller/session_management.rb b/actionpack/lib/action_controller/session/management.rb
index b556f04649..b556f04649 100644
--- a/actionpack/lib/action_controller/session_management.rb
+++ b/actionpack/lib/action_controller/session/management.rb
diff --git a/actionpack/lib/action_controller/assertions/dom_assertions.rb b/actionpack/lib/action_controller/testing/assertions/dom.rb
index 5ffe5f1883..5ffe5f1883 100644
--- a/actionpack/lib/action_controller/assertions/dom_assertions.rb
+++ b/actionpack/lib/action_controller/testing/assertions/dom.rb
diff --git a/actionpack/lib/action_controller/assertions/model_assertions.rb b/actionpack/lib/action_controller/testing/assertions/model.rb
index 3a7b39b106..3a7b39b106 100644
--- a/actionpack/lib/action_controller/assertions/model_assertions.rb
+++ b/actionpack/lib/action_controller/testing/assertions/model.rb
diff --git a/actionpack/lib/action_controller/assertions/response_assertions.rb b/actionpack/lib/action_controller/testing/assertions/response.rb
index 5976090273..5976090273 100644
--- a/actionpack/lib/action_controller/assertions/response_assertions.rb
+++ b/actionpack/lib/action_controller/testing/assertions/response.rb
diff --git a/actionpack/lib/action_controller/assertions/routing_assertions.rb b/actionpack/lib/action_controller/testing/assertions/routing.rb
index 5101751cea..5101751cea 100644
--- a/actionpack/lib/action_controller/assertions/routing_assertions.rb
+++ b/actionpack/lib/action_controller/testing/assertions/routing.rb
diff --git a/actionpack/lib/action_controller/assertions/selector_assertions.rb b/actionpack/lib/action_controller/testing/assertions/selector.rb
index 0d56ea5ef7..0d56ea5ef7 100644
--- a/actionpack/lib/action_controller/assertions/selector_assertions.rb
+++ b/actionpack/lib/action_controller/testing/assertions/selector.rb
diff --git a/actionpack/lib/action_controller/assertions/tag_assertions.rb b/actionpack/lib/action_controller/testing/assertions/tag.rb
index 80249e0e83..80249e0e83 100644
--- a/actionpack/lib/action_controller/assertions/tag_assertions.rb
+++ b/actionpack/lib/action_controller/testing/assertions/tag.rb
diff --git a/actionpack/lib/action_controller/integration.rb b/actionpack/lib/action_controller/testing/integration.rb
index 163ba84a3e..163ba84a3e 100644
--- a/actionpack/lib/action_controller/integration.rb
+++ b/actionpack/lib/action_controller/testing/integration.rb
diff --git a/actionpack/lib/action_controller/performance_test.rb b/actionpack/lib/action_controller/testing/performance.rb
index d88180087d..d88180087d 100644
--- a/actionpack/lib/action_controller/performance_test.rb
+++ b/actionpack/lib/action_controller/testing/performance.rb
diff --git a/actionpack/lib/action_controller/test_process.rb b/actionpack/lib/action_controller/testing/process.rb
index 22b97fc157..22b97fc157 100644
--- a/actionpack/lib/action_controller/test_process.rb
+++ b/actionpack/lib/action_controller/testing/process.rb
diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/testing/test_case.rb
index 0b0d0c799b..c14785ba83 100644
--- a/actionpack/lib/action_controller/test_case.rb
+++ b/actionpack/lib/action_controller/testing/test_case.rb
@@ -1,5 +1,5 @@
require 'active_support/test_case'
-require 'action_controller/test_process'
+require 'action_controller/testing/process'
module ActionController
# Superclass for ActionController functional tests. Functional tests allow you to
diff --git a/actionpack/lib/action_view/render/partials.rb b/actionpack/lib/action_view/render/partials.rb
index aa4c4af213..e337dcb63b 100644
--- a/actionpack/lib/action_view/render/partials.rb
+++ b/actionpack/lib/action_view/render/partials.rb
@@ -243,6 +243,34 @@ module ActionView
end
end
+ def _render_partial_with_block(layout, block, options)
+ @_proc_for_layout = block
+ concat(_render_partial(options.merge(:partial => layout)))
+ ensure
+ @_proc_for_layout = nil
+ end
+
+ def _render_partial_with_layout(layout, options)
+ if layout
+ prefix = controller && !layout.include?("/") ? controller.controller_path : nil
+ layout = find_by_parts(layout, formats, prefix, true)
+ end
+ content = _render_partial(options)
+ return _render_content_with_layout(content, layout, options[:locals])
+ end
+
+ def _deprecated_ivar_assign(template)
+ if respond_to?(:controller)
+ ivar = :"@#{template.variable_name}"
+ object =
+ if controller.instance_variable_defined?(ivar)
+ ActiveSupport::Deprecation::DeprecatedObjectProxy.new(
+ controller.instance_variable_get(ivar),
+ "#{ivar} will no longer be implicitly assigned to #{template.variable_name}")
+ end
+ end
+ end
+
def _array_like_objects
array_like = [Array]
if defined?(ActiveRecord)
diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb
index 30e2d863d0..67c51f01bd 100644
--- a/actionpack/test/abstract_unit.rb
+++ b/actionpack/test/abstract_unit.rb
@@ -20,8 +20,7 @@ rescue LoadError
end
require 'action_controller'
-require 'action_controller/cgi_ext'
-require 'action_controller/test_process'
+require 'action_controller/testing/process'
require 'action_view/test_case'
# Show backtraces for deprecated behavior for quicker cleanup.
diff --git a/actionpack/test/controller/send_file_test.rb b/actionpack/test/controller/send_file_test.rb
index 5fc79baa44..b703f340a0 100644
--- a/actionpack/test/controller/send_file_test.rb
+++ b/actionpack/test/controller/send_file_test.rb
@@ -155,7 +155,7 @@ class SendFileTest < ActionController::TestCase
define_method "test_default_send_#{method}_status" do
@controller.options = { :stream => false }
assert_nothing_raised { assert_not_nil process(method) }
- assert_equal ActionController::Base::DEFAULT_RENDER_STATUS_CODE, @response.status
+ assert_equal ActionController::DEFAULT_RENDER_STATUS_CODE, @response.status
end
end
end
diff --git a/actionpack/test/controller/test_test.rb b/actionpack/test/controller/test_test.rb
index ee7b8ade8c..5708a1768f 100644
--- a/actionpack/test/controller/test_test.rb
+++ b/actionpack/test/controller/test_test.rb
@@ -612,7 +612,7 @@ class CleanBacktraceTest < ActionController::TestCase
end
def test_should_clean_assertion_lines_from_backtrace
- path = File.expand_path("#{File.dirname(__FILE__)}/../../lib/action_controller")
+ path = File.expand_path("#{File.dirname(__FILE__)}/../../lib/action_controller/testing")
exception = ActiveSupport::TestCase::Assertion.new('message')
exception.set_backtrace ["#{path}/abc", "#{path}/assertions/def"]
clean_backtrace { raise exception }
diff --git a/activesupport/lib/active_support/memoizable.rb b/activesupport/lib/active_support/memoizable.rb
index 4ffb5d9520..8e9abeaf91 100644
--- a/activesupport/lib/active_support/memoizable.rb
+++ b/activesupport/lib/active_support/memoizable.rb
@@ -1,4 +1,42 @@
module ActiveSupport
+ class ConcurrentHash
+ def initialize(hash = {})
+ @backup_cache = hash.dup
+ @frozen_cache = hash.dup.freeze
+ @mutex = Mutex.new
+ end
+
+ def []=(k,v)
+ @mutex.synchronize { @backup_cache[k] = v }
+ @frozen_cache = @backup_cache.dup.freeze
+ end
+
+ def [](k)
+ if @frozen_cache.key?(k)
+ @frozen_cache[k]
+ else
+ @mutex.synchronize { @backup_cache[k] }
+ end
+ end
+
+ def empty?
+ @backup_cache.empty?
+ end
+ end
+
+ module SafelyMemoizable
+ def safely_memoize(*symbols)
+ symbols.each do |symbol|
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
+ def #{symbol}(*args)
+ memoized = @_memoized_#{symbol} || ::ActiveSupport::ConcurrentHash.new
+ memoized[args] ||= memoized_#{symbol}(*args)
+ end
+ RUBY
+ end
+ end
+ end
+
module Memoizable
def self.memoized_ivar_for(symbol)
"@_memoized_#{symbol.to_s.sub(/\?\Z/, '_query').sub(/!\Z/, '_bang')}".to_sym
diff --git a/railties/lib/dispatcher.rb b/railties/lib/dispatcher.rb
index 9f8b59aa3d..7f9a6221d9 100644
--- a/railties/lib/dispatcher.rb
+++ b/railties/lib/dispatcher.rb
@@ -20,5 +20,5 @@
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#++
-require 'action_controller/dispatcher'
+require 'action_controller/dispatch/dispatcher'
Dispatcher = ActionController::Dispatcher