aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack
diff options
context:
space:
mode:
authorPratik Naik <pratiknaik@gmail.com>2008-10-05 19:46:48 +0100
committerPratik Naik <pratiknaik@gmail.com>2008-10-05 19:46:48 +0100
commit6090513cfb8acb5554a6653a6f2cb87648585d41 (patch)
tree99bfd589a48153e33f19ae72baa6e98f5708a9b8 /actionpack
parent01159a6431bbc2dc7d7d95ce294c8567c954f39e (diff)
parent4df45d86097efbeabceecfe53d8ea2da9ccbb107 (diff)
downloadrails-6090513cfb8acb5554a6653a6f2cb87648585d41.tar.gz
rails-6090513cfb8acb5554a6653a6f2cb87648585d41.tar.bz2
rails-6090513cfb8acb5554a6653a6f2cb87648585d41.zip
Merge commit 'mainstream/master'
Conflicts: activerecord/lib/active_record/association_preload.rb
Diffstat (limited to 'actionpack')
-rw-r--r--actionpack/lib/action_controller/base.rb19
-rw-r--r--actionpack/lib/action_controller/dispatcher.rb30
-rw-r--r--actionpack/lib/action_controller/integration.rb2
-rwxr-xr-xactionpack/lib/action_controller/request.rb5
-rw-r--r--actionpack/lib/action_controller/rescue.rb130
-rw-r--r--actionpack/lib/action_controller/test_case.rb2
-rw-r--r--actionpack/lib/action_view/base.rb18
-rw-r--r--actionpack/lib/action_view/helpers/form_tag_helper.rb10
-rw-r--r--actionpack/test/abstract_unit.rb2
-rw-r--r--actionpack/test/controller/render_test.rb41
-rw-r--r--actionpack/test/controller/rescue_test.rb35
-rw-r--r--actionpack/test/template/form_tag_helper_test.rb6
12 files changed, 133 insertions, 167 deletions
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb
index 91f531f12c..413f6d48e5 100644
--- a/actionpack/lib/action_controller/base.rb
+++ b/actionpack/lib/action_controller/base.rb
@@ -290,8 +290,6 @@ module ActionController #:nodoc:
@@allow_concurrency = false
cattr_accessor :allow_concurrency
- @@guard = Monitor.new
-
# Modern REST web services often need to submit complex data to the web application.
# 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.
@@ -532,12 +530,7 @@ module ActionController #:nodoc:
assign_names
log_processing
-
- if @@allow_concurrency
- send(method, *arguments)
- else
- @@guard.synchronize { send(method, *arguments) }
- end
+ send(method, *arguments)
send_response
ensure
@@ -975,13 +968,15 @@ module ActionController #:nodoc:
# Sets the Last-Modified response header. Returns 304 Not Modified if the
# If-Modified-Since request header is <= last modified.
def last_modified!(utc_time)
- head(:not_modified) if response.last_modified!(utc_time)
+ response.last_modified= utc_time
+ head(:not_modified) if response.last_modified == request.if_modified_since
end
# Sets the ETag response header. Returns 304 Not Modified if the
# If-None-Match request header matches.
def etag!(etag)
- head(:not_modified) if response.etag!(etag)
+ response.etag = etag
+ head(:not_modified) if response.etag == request.if_none_match
end
# Clears the rendered results, allowing for another render to be performed.
@@ -1256,7 +1251,7 @@ module ActionController #:nodoc:
action_name = strip_out_controller(action_name)
end
end
- "#{self.class.controller_path}/#{action_name}"
+ "#{self.controller_path}/#{action_name}"
end
def strip_out_controller(path)
@@ -1264,7 +1259,7 @@ module ActionController #:nodoc:
end
def template_path_includes_controller?(path)
- self.class.controller_path.split('/')[-1] == path.split('/')[0]
+ self.controller_path.split('/')[-1] == path.split('/')[0]
end
def process_cleanup
diff --git a/actionpack/lib/action_controller/dispatcher.rb b/actionpack/lib/action_controller/dispatcher.rb
index bdae5f9d86..90c8400c11 100644
--- a/actionpack/lib/action_controller/dispatcher.rb
+++ b/actionpack/lib/action_controller/dispatcher.rb
@@ -2,6 +2,8 @@ module ActionController
# Dispatches requests to the appropriate controller and takes care of
# reloading the app after each request when Dependencies.load? is true.
class Dispatcher
+ @@guard = Mutex.new
+
class << self
def define_dispatcher_callbacks(cache_classes)
unless cache_classes
@@ -20,6 +22,7 @@ module ActionController
end
if defined?(ActiveRecord)
+ after_dispatch :checkin_connections
before_dispatch { ActiveRecord::Base.verify_active_connections! }
to_prepare(:activerecord_instantiate_observers) { ActiveRecord::Base.instantiate_observers }
end
@@ -98,7 +101,7 @@ module ActionController
@output, @request, @response = output, request, response
end
- def dispatch
+ def dispatch_unlocked
begin
run_callbacks :before_dispatch
handle_request
@@ -109,6 +112,16 @@ module ActionController
end
end
+ def dispatch
+ if ActionController::Base.allow_concurrency
+ dispatch_unlocked
+ else
+ @@guard.synchronize do
+ dispatch_unlocked
+ end
+ end
+ end
+
def dispatch_cgi(cgi, session_options)
if cgi ||= self.class.failsafe_response(@output, '400 Bad Request') { CGI.new }
@request = CgiRequest.new(cgi, session_options)
@@ -145,6 +158,21 @@ module ActionController
Base.logger.flush
end
+ def mark_as_test_request!
+ @test_request = true
+ self
+ end
+
+ def test_request?
+ @test_request
+ end
+
+ def checkin_connections
+ # Don't return connection (and peform implicit rollback) if this request is a part of integration test
+ return if test_request?
+ ActiveRecord::Base.clear_active_connections!
+ end
+
protected
def handle_request
@controller = Routing::Routes.recognize(@request)
diff --git a/actionpack/lib/action_controller/integration.rb b/actionpack/lib/action_controller/integration.rb
index a98c1af7f9..fc473c269c 100644
--- a/actionpack/lib/action_controller/integration.rb
+++ b/actionpack/lib/action_controller/integration.rb
@@ -276,7 +276,7 @@ module ActionController
ActionController::Base.clear_last_instantiation!
env['rack.input'] = data.is_a?(IO) ? data : StringIO.new(data || '')
- @status, @headers, result_body = ActionController::Dispatcher.new.call(env)
+ @status, @headers, result_body = ActionController::Dispatcher.new.mark_as_test_request!.call(env)
@request_count += 1
@controller = ActionController::Base.last_instantiation
diff --git a/actionpack/lib/action_controller/request.rb b/actionpack/lib/action_controller/request.rb
index 8e6cfb41dc..5e492e3ee1 100755
--- a/actionpack/lib/action_controller/request.rb
+++ b/actionpack/lib/action_controller/request.rb
@@ -167,7 +167,7 @@ module ActionController
parameter_format = parameters[:format]
if parameter_format
- parameter_format.to_sym
+ parameter_format
elsif xhr?
:js
else
@@ -176,8 +176,7 @@ module ActionController
end
def cache_format
- parameter_format = parameters[:format]
- parameter_format && parameter_format.to_sym
+ parameters[:format]
end
# Returns true if the request's "X-Requested-With" header contains
diff --git a/actionpack/lib/action_controller/rescue.rb b/actionpack/lib/action_controller/rescue.rb
index 83c4218af4..ec8e9b92d5 100644
--- a/actionpack/lib/action_controller/rescue.rb
+++ b/actionpack/lib/action_controller/rescue.rb
@@ -41,10 +41,9 @@ module ActionController #:nodoc:
base.rescue_templates = Hash.new(DEFAULT_RESCUE_TEMPLATE)
base.rescue_templates.update DEFAULT_RESCUE_TEMPLATES
- base.class_inheritable_array :rescue_handlers
- base.rescue_handlers = []
-
base.extend(ClassMethods)
+ base.send :include, ActiveSupport::Rescuable
+
base.class_eval do
alias_method_chain :perform_action, :rescue
end
@@ -54,82 +53,12 @@ module ActionController #:nodoc:
def process_with_exception(request, response, exception) #:nodoc:
new.process(request, response, :rescue_action, exception)
end
-
- # Rescue exceptions raised in controller actions.
- #
- # <tt>rescue_from</tt> receives a series of exception classes or class
- # names, and a trailing <tt>:with</tt> option with the name of a method
- # or a Proc object to be called to handle them. Alternatively a block can
- # be given.
- #
- # Handlers that take one argument will be called with the exception, so
- # that the exception can be inspected when dealing with it.
- #
- # Handlers are inherited. They are searched from right to left, from
- # bottom to top, and up the hierarchy. The handler of the first class for
- # which <tt>exception.is_a?(klass)</tt> holds true is the one invoked, if
- # any.
- #
- # class ApplicationController < ActionController::Base
- # rescue_from User::NotAuthorized, :with => :deny_access # self defined exception
- # rescue_from ActiveRecord::RecordInvalid, :with => :show_errors
- #
- # rescue_from 'MyAppError::Base' do |exception|
- # render :xml => exception, :status => 500
- # end
- #
- # protected
- # def deny_access
- # ...
- # end
- #
- # def show_errors(exception)
- # exception.record.new_record? ? ...
- # end
- # end
- def rescue_from(*klasses, &block)
- options = klasses.extract_options!
- unless options.has_key?(:with)
- block_given? ? options[:with] = block : raise(ArgumentError, "Need a handler. Supply an options hash that has a :with key as the last argument.")
- end
-
- klasses.each do |klass|
- key = if klass.is_a?(Class) && klass <= Exception
- klass.name
- elsif klass.is_a?(String)
- klass
- else
- raise(ArgumentError, "#{klass} is neither an Exception nor a String")
- end
-
- # Order is important, we put the pair at the end. When dealing with an
- # exception we will follow the documented order going from right to left.
- rescue_handlers << [key, options[:with]]
- end
- end
end
protected
# Exception handler called when the performance of an action raises an exception.
def rescue_action(exception)
- if handler_for_rescue(exception)
- rescue_action_with_handler(exception)
- else
- log_error(exception) if logger
- erase_results if performed?
-
- # Let the exception alter the response if it wants.
- # For example, MethodNotAllowed sets the Allow header.
- if exception.respond_to?(:handle_response!)
- exception.handle_response!(response)
- end
-
- if consider_all_requests_local || local_request?
- rescue_action_locally(exception)
- else
- rescue_action_in_public(exception)
- end
- end
+ rescue_with_handler(exception) || rescue_action_without_handler(exception)
end
# Overwrite to implement custom logging of errors. By default logs as fatal.
@@ -185,15 +114,20 @@ module ActionController #:nodoc:
render_for_file(rescues_path("layout"), response_code_for_rescue(exception))
end
- # Tries to rescue the exception by looking up and calling a registered handler.
- def rescue_action_with_handler(exception)
- if handler = handler_for_rescue(exception)
- if handler.arity != 0
- handler.call(exception)
- else
- handler.call
- end
- true # don't rely on the return value of the handler
+ def rescue_action_without_handler(exception)
+ log_error(exception) if logger
+ erase_results if performed?
+
+ # Let the exception alter the response if it wants.
+ # For example, MethodNotAllowed sets the Allow header.
+ if exception.respond_to?(:handle_response!)
+ exception.handle_response!(response)
+ end
+
+ if consider_all_requests_local || local_request?
+ rescue_action_locally(exception)
+ else
+ rescue_action_in_public(exception)
end
end
@@ -216,36 +150,6 @@ module ActionController #:nodoc:
rescue_responses[exception.class.name]
end
- def handler_for_rescue(exception)
- # We go from right to left because pairs are pushed onto rescue_handlers
- # as rescue_from declarations are found.
- _, handler = *rescue_handlers.reverse.detect do |klass_name, handler|
- # The purpose of allowing strings in rescue_from is to support the
- # declaration of handler associations for exception classes whose
- # definition is yet unknown.
- #
- # Since this loop needs the constants it would be inconsistent to
- # assume they should exist at this point. An early raised exception
- # could trigger some other handler and the array could include
- # precisely a string whose corresponding constant has not yet been
- # seen. This is why we are tolerant to unknown constants.
- #
- # Note that this tolerance only matters if the exception was given as
- # a string, otherwise a NameError will be raised by the interpreter
- # itself when rescue_from CONSTANT is executed.
- klass = self.class.const_get(klass_name) rescue nil
- klass ||= klass_name.constantize rescue nil
- exception.is_a?(klass) if klass
- end
-
- case handler
- when Symbol
- method(handler)
- when Proc
- handler.bind(self)
- end
- end
-
def clean_backtrace(exception)
if backtrace = exception.backtrace
if defined?(RAILS_ROOT)
diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb
index 3e66947d5f..6a39039504 100644
--- a/actionpack/lib/action_controller/test_case.rb
+++ b/actionpack/lib/action_controller/test_case.rb
@@ -84,7 +84,7 @@ module ActionController
module RaiseActionExceptions
attr_accessor :exception
- def rescue_action(e)
+ def rescue_action_without_handler(e)
self.exception = e
if request.remote_addr == "0.0.0.0"
diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb
index 8c00670087..8df10c40cc 100644
--- a/actionpack/lib/action_view/base.rb
+++ b/actionpack/lib/action_view/base.rb
@@ -290,21 +290,23 @@ module ActionView #:nodoc:
private
attr_accessor :_first_render, :_last_render
- # Evaluate the local assigns and pushes them to the view.
+ # Evaluates the local assigns and controller ivars, pushes them to the view.
def _evaluate_assigns_and_ivars #:nodoc:
unless @assigns_added
@assigns.each { |key, value| instance_variable_set("@#{key}", value) }
-
- if @controller
- variables = @controller.instance_variables
- variables -= @controller.protected_instance_variables if @controller.respond_to?(:protected_instance_variables)
- variables.each {|name| instance_variable_set(name, @controller.instance_variable_get(name)) }
- end
-
+ _copy_ivars_from_controller
@assigns_added = true
end
end
+ def _copy_ivars_from_controller #:nodoc:
+ if @controller
+ variables = @controller.instance_variable_names
+ variables -= @controller.protected_instance_variables if @controller.respond_to?(:protected_instance_variables)
+ variables.each { |name| instance_variable_set(name, @controller.instance_variable_get(name)) }
+ end
+ end
+
def _set_controller_content_type(content_type) #:nodoc:
if controller.respond_to?(:response)
controller.response.content_type ||= content_type
diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb
index 294c22521e..208bf91dd4 100644
--- a/actionpack/lib/action_view/helpers/form_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb
@@ -403,6 +403,7 @@ module ActionView
# Creates a field set for grouping HTML form elements.
#
# <tt>legend</tt> will become the fieldset's title (optional as per W3C).
+ # <tt>options</tt> accept the same values as tag.
#
# === Examples
# <% field_set_tag do %>
@@ -414,9 +415,14 @@ module ActionView
# <p><%= text_field_tag 'name' %></p>
# <% end %>
# # => <fieldset><legend>Your details</legend><p><input id="name" name="name" type="text" /></p></fieldset>
- def field_set_tag(legend = nil, &block)
+ #
+ # <% field_set_tag nil, :class => 'format' do %>
+ # <p><%= text_field_tag 'name' %></p>
+ # <% end %>
+ # # => <fieldset class="format"><p><input id="name" name="name" type="text" /></p></fieldset>
+ def field_set_tag(legend = nil, options = nil, &block)
content = capture(&block)
- concat(tag(:fieldset, {}, true))
+ concat(tag(:fieldset, options, true))
concat(content_tag(:legend, legend)) unless legend.blank?
concat(content)
concat("</fieldset>")
diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb
index 9db4cddd6a..673efa6af0 100644
--- a/actionpack/test/abstract_unit.rb
+++ b/actionpack/test/abstract_unit.rb
@@ -1,5 +1,5 @@
$:.unshift(File.dirname(__FILE__) + '/../lib')
-$:.unshift(File.dirname(__FILE__) + '/../../activesupport/lib/active_support')
+$:.unshift(File.dirname(__FILE__) + '/../../activesupport/lib')
$:.unshift(File.dirname(__FILE__) + '/fixtures/helpers')
require 'yaml'
diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb
index af7b5dde62..5a6ca98b2e 100644
--- a/actionpack/test/controller/render_test.rb
+++ b/actionpack/test/controller/render_test.rb
@@ -39,6 +39,16 @@ class TestController < ActionController::Base
render :action => 'hello_world'
end
end
+
+ def conditional_hello_with_bangs
+ render :action => 'hello_world'
+ end
+ before_filter :handle_last_modified_and_etags, :only=>:conditional_hello_with_bangs
+
+ def handle_last_modified_and_etags
+ last_modified! Time.now.utc.beginning_of_day
+ etag! [:foo, 123]
+ end
def render_hello_world
render :template => "test/hello_world"
@@ -1306,6 +1316,7 @@ class EtagRenderTest < Test::Unit::TestCase
@controller = TestController.new
@request.host = "www.nextangle.com"
+ @expected_bang_etag = etag_for(expand_key([:foo, 123]))
end
def test_render_200_should_set_etag
@@ -1365,11 +1376,27 @@ class EtagRenderTest < Test::Unit::TestCase
assert_equal "<wrapper>\n<html>\n <p>Hello </p>\n<p>This is grand!</p>\n</html>\n</wrapper>\n", @response.body
assert_equal etag_for("<wrapper>\n<html>\n <p>Hello </p>\n<p>This is grand!</p>\n</html>\n</wrapper>\n"), @response.headers['ETag']
end
-
+
+ def test_etag_with_bang_should_set_etag
+ get :conditional_hello_with_bangs
+ assert_equal @expected_bang_etag, @response.headers["ETag"]
+ assert_response :success
+ end
+
+ def test_etag_with_bang_should_obey_if_none_match
+ @request.if_none_match = @expected_bang_etag
+ get :conditional_hello_with_bangs
+ assert_response :not_modified
+ end
+
protected
def etag_for(text)
%("#{Digest::MD5.hexdigest(text)}")
end
+
+ def expand_key(args)
+ ActiveSupport::Cache.expand_cache_key(args)
+ end
end
class LastModifiedRenderTest < Test::Unit::TestCase
@@ -1402,6 +1429,18 @@ class LastModifiedRenderTest < Test::Unit::TestCase
assert !@response.body.blank?
assert_equal @last_modified, @response.headers['Last-Modified']
end
+
+ def test_request_with_bang_gets_last_modified
+ get :conditional_hello_with_bangs
+ assert_equal @last_modified, @response.headers['Last-Modified']
+ assert_response :success
+ end
+
+ def test_request_with_bang_obeys_last_modified
+ @request.if_modified_since = @last_modified
+ get :conditional_hello_with_bangs
+ assert_response :not_modified
+ end
end
class RenderingLoggingTest < Test::Unit::TestCase
diff --git a/actionpack/test/controller/rescue_test.rb b/actionpack/test/controller/rescue_test.rb
index da076d2090..32c6c013f1 100644
--- a/actionpack/test/controller/rescue_test.rb
+++ b/actionpack/test/controller/rescue_test.rb
@@ -75,7 +75,7 @@ class RescueController < ActionController::Base
def method_not_allowed
raise ActionController::MethodNotAllowed.new(:get, :head, :put)
end
-
+
def not_implemented
raise ActionController::NotImplemented.new(:get, :put)
end
@@ -107,7 +107,7 @@ class RescueController < ActionController::Base
def record_invalid_raise_as_string
raise RecordInvalidToRescueAsString
end
-
+
def bad_gateway
raise BadGateway
end
@@ -135,18 +135,19 @@ class RescueController < ActionController::Base
end
end
-class RescueTest < Test::Unit::TestCase
+class RescueControllerTest < ActionController::TestCase
FIXTURE_PUBLIC = "#{File.dirname(__FILE__)}/../fixtures".freeze
- def setup
- @controller = RescueController.new
- @request = ActionController::TestRequest.new
- @response = ActionController::TestResponse.new
+ setup :set_all_requests_local
+ setup :populate_exception_object
+ def set_all_requests_local
RescueController.consider_all_requests_local = true
@request.remote_addr = '1.2.3.4'
@request.host = 'example.com'
+ end
+ def populate_exception_object
begin
raise 'foo'
rescue => @exception
@@ -307,7 +308,7 @@ class RescueTest < Test::Unit::TestCase
assert_nil @controller.send(:clean_backtrace, Exception.new)
end
end
-
+
def test_not_implemented
with_all_requests_local false do
with_rails_public_path(".") do
@@ -463,14 +464,7 @@ class ExceptionInheritanceRescueController < ActionController::Base
end
end
-class ExceptionInheritanceRescueTest < Test::Unit::TestCase
-
- def setup
- @controller = ExceptionInheritanceRescueController.new
- @request = ActionController::TestRequest.new
- @response = ActionController::TestResponse.new
- end
-
+class ExceptionInheritanceRescueControllerTest < ActionController::TestCase
def test_bottom_first
get :raise_grandchild_exception
assert_response :no_content
@@ -500,14 +494,7 @@ class ControllerInheritanceRescueController < ExceptionInheritanceRescueControll
end
end
-class ControllerInheritanceRescueControllerTest < Test::Unit::TestCase
-
- def setup
- @controller = ControllerInheritanceRescueController.new
- @request = ActionController::TestRequest.new
- @response = ActionController::TestResponse.new
- end
-
+class ControllerInheritanceRescueControllerTest < ActionController::TestCase
def test_first_exception_in_child_controller
get :raise_first_exception_in_child_controller
assert_response :gone
diff --git a/actionpack/test/template/form_tag_helper_test.rb b/actionpack/test/template/form_tag_helper_test.rb
index 6473d011d5..ad8baef5e4 100644
--- a/actionpack/test/template/form_tag_helper_test.rb
+++ b/actionpack/test/template/form_tag_helper_test.rb
@@ -271,6 +271,12 @@ class FormTagHelperTest < ActionView::TestCase
expected = %(<fieldset>Hello world!</fieldset>)
assert_dom_equal expected, output_buffer
+
+ self.output_buffer = ''
+ field_set_tag('', :class => 'format') { concat "Hello world!" }
+
+ expected = %(<fieldset class="format">Hello world!</fieldset>)
+ assert_dom_equal expected, output_buffer
end
def protect_against_forgery?